mirror of
https://github.com/oven-sh/bun
synced 2026-02-28 20:40:59 +01:00
Compare commits
25 Commits
claude/fix
...
nektro-pat
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
2914a9643c | ||
|
|
66777f854b | ||
|
|
1d63b09bfd | ||
|
|
1ccc353e3e | ||
|
|
0dc55100fa | ||
|
|
dfb4aac6d1 | ||
|
|
a8a75121e8 | ||
|
|
0849fb1ab0 | ||
|
|
358dbd8ef6 | ||
|
|
786689f55b | ||
|
|
7227067ce8 | ||
|
|
e3eddea10f | ||
|
|
3a37669977 | ||
|
|
be6ee71407 | ||
|
|
72b7103376 | ||
|
|
795372a5d8 | ||
|
|
7414cf267a | ||
|
|
8b47a57762 | ||
|
|
0e4d12d01a | ||
|
|
8de28f26b8 | ||
|
|
583c97bdcd | ||
|
|
7134fba5c1 | ||
|
|
292775ee94 | ||
|
|
b45e696fe5 | ||
|
|
9567c9776b |
@@ -584,7 +584,7 @@ LIBUS_SOCKET_DESCRIPTOR bsd_create_socket(int domain, int type, int protocol, in
|
||||
|
||||
if (UNLIKELY(created_fd == -1)) {
|
||||
if (err != NULL) {
|
||||
*err = errno;
|
||||
*err = LIBUS_ERR;
|
||||
}
|
||||
return LIBUS_SOCKET_ERROR;
|
||||
}
|
||||
@@ -597,7 +597,7 @@ LIBUS_SOCKET_DESCRIPTOR bsd_create_socket(int domain, int type, int protocol, in
|
||||
|
||||
if (UNLIKELY(created_fd == -1)) {
|
||||
if (err != NULL) {
|
||||
*err = errno;
|
||||
*err = LIBUS_ERR;
|
||||
}
|
||||
return LIBUS_SOCKET_ERROR;
|
||||
}
|
||||
@@ -742,7 +742,7 @@ ssize_t bsd_recvmsg(LIBUS_SOCKET_DESCRIPTOR fd, struct msghdr *msg, int flags) {
|
||||
#if !defined(_WIN32)
|
||||
#include <sys/uio.h>
|
||||
|
||||
ssize_t bsd_write2(LIBUS_SOCKET_DESCRIPTOR fd, const char *header, int header_length, const char *payload, int payload_length) {
|
||||
ssize_t bsd_write2(LIBUS_SOCKET_DESCRIPTOR fd, const char *header, int header_length, const char *payload, int payload_length, int *error) {
|
||||
struct iovec chunks[2];
|
||||
|
||||
chunks[0].iov_base = (char *)header;
|
||||
@@ -756,15 +756,18 @@ ssize_t bsd_write2(LIBUS_SOCKET_DESCRIPTOR fd, const char *header, int header_le
|
||||
if (UNLIKELY(IS_EINTR(written))) {
|
||||
continue;
|
||||
}
|
||||
if (written < 0) {
|
||||
if (error != NULL) *error = LIBUS_ERR;
|
||||
}
|
||||
|
||||
return written;
|
||||
}
|
||||
}
|
||||
#else
|
||||
ssize_t bsd_write2(LIBUS_SOCKET_DESCRIPTOR fd, const char *header, int header_length, const char *payload, int payload_length) {
|
||||
ssize_t written = bsd_send(fd, header, header_length, 0);
|
||||
ssize_t bsd_write2(LIBUS_SOCKET_DESCRIPTOR fd, const char *header, int header_length, const char *payload, int payload_length, int *error) {
|
||||
ssize_t written = bsd_send(fd, header, header_length, 0, error);
|
||||
if (written == header_length) {
|
||||
ssize_t second_write = bsd_send(fd, payload, payload_length, 0);
|
||||
ssize_t second_write = bsd_send(fd, payload, payload_length, 0, error);
|
||||
if (second_write > 0) {
|
||||
written += second_write;
|
||||
}
|
||||
@@ -773,7 +776,7 @@ ssize_t bsd_write2(LIBUS_SOCKET_DESCRIPTOR fd, const char *header, int header_le
|
||||
}
|
||||
#endif
|
||||
|
||||
ssize_t bsd_send(LIBUS_SOCKET_DESCRIPTOR fd, const char *buf, int length, int msg_more) {
|
||||
ssize_t bsd_send(LIBUS_SOCKET_DESCRIPTOR fd, const char *buf, int length, int msg_more, int *error) {
|
||||
while (1) {
|
||||
// MSG_MORE (Linux), MSG_PARTIAL (Windows), TCP_NOPUSH (BSD)
|
||||
|
||||
@@ -788,6 +791,10 @@ ssize_t bsd_send(LIBUS_SOCKET_DESCRIPTOR fd, const char *buf, int length, int ms
|
||||
// use TCP_NOPUSH
|
||||
ssize_t rc = send(fd, buf, length, MSG_NOSIGNAL | MSG_DONTWAIT);
|
||||
#endif
|
||||
if (rc < 0) {
|
||||
if (error != NULL) *error = LIBUS_ERR;
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (UNLIKELY(IS_EINTR(rc))) {
|
||||
continue;
|
||||
@@ -826,14 +833,17 @@ static int us_internal_bind_and_listen(LIBUS_SOCKET_DESCRIPTOR listenFd, struct
|
||||
while (IS_EINTR(result));
|
||||
|
||||
if (result == -1) {
|
||||
*error = LIBUS_ERR;
|
||||
if (error != NULL) *error = LIBUS_ERR;
|
||||
return -1;
|
||||
}
|
||||
|
||||
do
|
||||
result = listen(listenFd, backlog);
|
||||
while (IS_EINTR(result));
|
||||
*error = LIBUS_ERR;
|
||||
if (result == -1) {
|
||||
if (error != NULL) *error = LIBUS_ERR;
|
||||
return -1;
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
@@ -956,7 +966,7 @@ LIBUS_SOCKET_DESCRIPTOR bsd_create_listen_socket(const char *host, int port, int
|
||||
struct addrinfo *listenAddr;
|
||||
for (struct addrinfo *a = result; a != NULL; a = a->ai_next) {
|
||||
if (a->ai_family == AF_INET6) {
|
||||
listenFd = bsd_create_socket(a->ai_family, a->ai_socktype, a->ai_protocol, NULL);
|
||||
listenFd = bsd_create_socket(a->ai_family, a->ai_socktype, a->ai_protocol, error);
|
||||
if (listenFd == LIBUS_SOCKET_ERROR) {
|
||||
continue;
|
||||
}
|
||||
@@ -973,7 +983,7 @@ LIBUS_SOCKET_DESCRIPTOR bsd_create_listen_socket(const char *host, int port, int
|
||||
|
||||
for (struct addrinfo *a = result; a != NULL; a = a->ai_next) {
|
||||
if (a->ai_family == AF_INET) {
|
||||
listenFd = bsd_create_socket(a->ai_family, a->ai_socktype, a->ai_protocol, NULL);
|
||||
listenFd = bsd_create_socket(a->ai_family, a->ai_socktype, a->ai_protocol, error);
|
||||
if (listenFd == LIBUS_SOCKET_ERROR) {
|
||||
continue;
|
||||
}
|
||||
@@ -1001,7 +1011,7 @@ LIBUS_SOCKET_DESCRIPTOR bsd_create_listen_socket(const char *host, int port, int
|
||||
#include <sys/stat.h>
|
||||
#include <stddef.h>
|
||||
|
||||
static LIBUS_SOCKET_DESCRIPTOR bsd_create_unix_socket_address(const char *path, size_t path_len, int* dirfd_linux_workaround_for_unix_path_len, struct sockaddr_un *server_address, size_t* addrlen) {
|
||||
static LIBUS_SOCKET_DESCRIPTOR bsd_create_unix_socket_address(const char *path, size_t path_len, int* dirfd_linux_workaround_for_unix_path_len, struct sockaddr_un *server_address, size_t* addrlen, int *error) {
|
||||
memset(server_address, 0, sizeof(struct sockaddr_un));
|
||||
server_address->sun_family = AF_UNIX;
|
||||
|
||||
@@ -1010,7 +1020,7 @@ static LIBUS_SOCKET_DESCRIPTOR bsd_create_unix_socket_address(const char *path,
|
||||
// simulate ENOENT
|
||||
SetLastError(ERROR_PATH_NOT_FOUND);
|
||||
#else
|
||||
errno = ENOENT;
|
||||
*error = ENOENT;
|
||||
#endif
|
||||
return LIBUS_SOCKET_ERROR;
|
||||
}
|
||||
@@ -1029,13 +1039,13 @@ static LIBUS_SOCKET_DESCRIPTOR bsd_create_unix_socket_address(const char *path,
|
||||
|
||||
// if the path is just a single character, or the path is too long, we cannot use this method
|
||||
if (dirname_len < 2 || (path_len - dirname_len + 1) >= sizeof(server_address->sun_path)) {
|
||||
errno = ENAMETOOLONG;
|
||||
if (error != NULL) *error = EINVAL;
|
||||
return LIBUS_SOCKET_ERROR;
|
||||
}
|
||||
|
||||
char dirname_buf[4096];
|
||||
if (dirname_len + 1 > sizeof(dirname_buf)) {
|
||||
errno = ENAMETOOLONG;
|
||||
if (error != NULL) *error = EINVAL;
|
||||
return LIBUS_SOCKET_ERROR;
|
||||
}
|
||||
|
||||
@@ -1044,14 +1054,14 @@ static LIBUS_SOCKET_DESCRIPTOR bsd_create_unix_socket_address(const char *path,
|
||||
|
||||
int socket_dir_fd = open(dirname_buf, O_CLOEXEC | O_PATH | O_DIRECTORY, 0700);
|
||||
if (socket_dir_fd == -1) {
|
||||
errno = ENAMETOOLONG;
|
||||
if (error != NULL) *error = LIBUS_ERR;
|
||||
return LIBUS_SOCKET_ERROR;
|
||||
}
|
||||
|
||||
int sun_path_len = snprintf(server_address->sun_path, sizeof(server_address->sun_path), "/proc/self/fd/%d/%s", socket_dir_fd, path + dirname_len);
|
||||
if (sun_path_len >= sizeof(server_address->sun_path) || sun_path_len < 0) {
|
||||
if (error != NULL) *error = ENAMETOOLONG;
|
||||
close(socket_dir_fd);
|
||||
errno = ENAMETOOLONG;
|
||||
return LIBUS_SOCKET_ERROR;
|
||||
}
|
||||
|
||||
@@ -1074,7 +1084,10 @@ static LIBUS_SOCKET_DESCRIPTOR bsd_create_unix_socket_address(const char *path,
|
||||
// simulate ENAMETOOLONG
|
||||
SetLastError(ERROR_FILENAME_EXCED_RANGE);
|
||||
#else
|
||||
errno = ENAMETOOLONG;
|
||||
// was ENAMETOOLONG but changed to EINVAL to align with node's UV_PIPE_NO_TRUNCATE flag
|
||||
// https://docs.libuv.org/en/v1.x/pipe.html#c.uv_pipe_bind2
|
||||
// https://github.com/nodejs/node/blob/v24.0.0/src/pipe_wrap.cc#L168
|
||||
*error = EINVAL;
|
||||
#endif
|
||||
|
||||
return LIBUS_SOCKET_ERROR;
|
||||
@@ -1087,7 +1100,7 @@ static LIBUS_SOCKET_DESCRIPTOR bsd_create_unix_socket_address(const char *path,
|
||||
static LIBUS_SOCKET_DESCRIPTOR internal_bsd_create_listen_socket_unix(const char* path, int options, struct sockaddr_un* server_address, size_t addrlen, int* error) {
|
||||
LIBUS_SOCKET_DESCRIPTOR listenFd = LIBUS_SOCKET_ERROR;
|
||||
|
||||
listenFd = bsd_create_socket(AF_UNIX, SOCK_STREAM, 0, NULL);
|
||||
listenFd = bsd_create_socket(AF_UNIX, SOCK_STREAM, 0, error);
|
||||
|
||||
if (listenFd == LIBUS_SOCKET_ERROR) {
|
||||
return LIBUS_SOCKET_ERROR;
|
||||
@@ -1119,7 +1132,7 @@ LIBUS_SOCKET_DESCRIPTOR bsd_create_listen_socket_unix(const char *path, size_t l
|
||||
int dirfd_linux_workaround_for_unix_path_len = -1;
|
||||
struct sockaddr_un server_address;
|
||||
size_t addrlen = 0;
|
||||
if (bsd_create_unix_socket_address(path, len, &dirfd_linux_workaround_for_unix_path_len, &server_address, &addrlen)) {
|
||||
if (bsd_create_unix_socket_address(path, len, &dirfd_linux_workaround_for_unix_path_len, &server_address, &addrlen, error)) {
|
||||
return LIBUS_SOCKET_ERROR;
|
||||
}
|
||||
|
||||
@@ -1230,11 +1243,7 @@ LIBUS_SOCKET_DESCRIPTOR bsd_create_udp_socket(const char *host, int port, int op
|
||||
/* We bind here as well */
|
||||
if (bind(listenFd, listenAddr->ai_addr, (socklen_t) listenAddr->ai_addrlen)) {
|
||||
if (err != NULL) {
|
||||
#ifdef _WIN32
|
||||
*err = WSAGetLastError();
|
||||
#else
|
||||
*err = errno;
|
||||
#endif
|
||||
*err = LIBUS_ERR;
|
||||
}
|
||||
bsd_close_socket(listenFd);
|
||||
freeaddrinfo(result);
|
||||
@@ -1333,7 +1342,7 @@ int bsd_disconnect_udp_socket(LIBUS_SOCKET_DESCRIPTOR fd) {
|
||||
// return 0; // no ecn defaults to 0
|
||||
// }
|
||||
|
||||
static int bsd_do_connect_raw(LIBUS_SOCKET_DESCRIPTOR fd, struct sockaddr *addr, size_t namelen)
|
||||
static int bsd_do_connect_raw(LIBUS_SOCKET_DESCRIPTOR fd, struct sockaddr *addr, size_t namelen, int *error)
|
||||
{
|
||||
#ifdef _WIN32
|
||||
while (1) {
|
||||
@@ -1352,6 +1361,7 @@ static int bsd_do_connect_raw(LIBUS_SOCKET_DESCRIPTOR fd, struct sockaddr *addr,
|
||||
continue;
|
||||
}
|
||||
default: {
|
||||
if (error != NULL) *error = us_wsa_to_libuv_errno(err);
|
||||
return err;
|
||||
}
|
||||
}
|
||||
@@ -1372,7 +1382,8 @@ static int bsd_do_connect_raw(LIBUS_SOCKET_DESCRIPTOR fd, struct sockaddr *addr,
|
||||
return 0;
|
||||
}
|
||||
|
||||
return errno;
|
||||
if (error != NULL) *error = LIBUS_ERR;
|
||||
return r;
|
||||
}
|
||||
|
||||
return 0;
|
||||
@@ -1414,8 +1425,8 @@ static int is_loopback(struct sockaddr_storage *sockaddr) {
|
||||
}
|
||||
#endif
|
||||
|
||||
LIBUS_SOCKET_DESCRIPTOR bsd_create_connect_socket(struct sockaddr_storage *addr, int options) {
|
||||
LIBUS_SOCKET_DESCRIPTOR fd = bsd_create_socket(addr->ss_family, SOCK_STREAM, 0, NULL);
|
||||
LIBUS_SOCKET_DESCRIPTOR bsd_create_connect_socket(struct sockaddr_storage *addr, int options, int *error) {
|
||||
LIBUS_SOCKET_DESCRIPTOR fd = bsd_create_socket(addr->ss_family, SOCK_STREAM, 0, error);
|
||||
if (fd == LIBUS_SOCKET_ERROR) {
|
||||
return LIBUS_SOCKET_ERROR;
|
||||
}
|
||||
@@ -1452,7 +1463,7 @@ LIBUS_SOCKET_DESCRIPTOR bsd_create_connect_socket(struct sockaddr_storage *addr,
|
||||
}
|
||||
|
||||
#endif
|
||||
int rc = bsd_do_connect_raw(fd, (struct sockaddr*) addr, addr->ss_family == AF_INET ? sizeof(struct sockaddr_in) : sizeof(struct sockaddr_in6));
|
||||
int rc = bsd_do_connect_raw(fd, (struct sockaddr*) addr, addr->ss_family == AF_INET ? sizeof(struct sockaddr_in) : sizeof(struct sockaddr_in6), error);
|
||||
|
||||
if (rc != 0) {
|
||||
bsd_close_socket(fd);
|
||||
@@ -1461,8 +1472,8 @@ LIBUS_SOCKET_DESCRIPTOR bsd_create_connect_socket(struct sockaddr_storage *addr,
|
||||
return fd;
|
||||
}
|
||||
|
||||
static LIBUS_SOCKET_DESCRIPTOR internal_bsd_create_connect_socket_unix(const char *server_path, size_t len, int options, struct sockaddr_un* server_address, const size_t addrlen) {
|
||||
LIBUS_SOCKET_DESCRIPTOR fd = bsd_create_socket(AF_UNIX, SOCK_STREAM, 0, NULL);
|
||||
static LIBUS_SOCKET_DESCRIPTOR internal_bsd_create_connect_socket_unix(const char *server_path, size_t len, int options, struct sockaddr_un* server_address, const size_t addrlen, int *error) {
|
||||
LIBUS_SOCKET_DESCRIPTOR fd = bsd_create_socket(AF_UNIX, SOCK_STREAM, 0, error);
|
||||
|
||||
if (fd == LIBUS_SOCKET_ERROR) {
|
||||
return LIBUS_SOCKET_ERROR;
|
||||
@@ -1470,7 +1481,7 @@ static LIBUS_SOCKET_DESCRIPTOR internal_bsd_create_connect_socket_unix(const cha
|
||||
|
||||
win32_set_nonblocking(fd);
|
||||
|
||||
if (bsd_do_connect_raw(fd, (struct sockaddr *)server_address, addrlen) != 0) {
|
||||
if (bsd_do_connect_raw(fd, (struct sockaddr *)server_address, addrlen, error) != 0) {
|
||||
bsd_close_socket(fd);
|
||||
return LIBUS_SOCKET_ERROR;
|
||||
}
|
||||
@@ -1478,15 +1489,15 @@ static LIBUS_SOCKET_DESCRIPTOR internal_bsd_create_connect_socket_unix(const cha
|
||||
return fd;
|
||||
}
|
||||
|
||||
LIBUS_SOCKET_DESCRIPTOR bsd_create_connect_socket_unix(const char *server_path, size_t len, int options) {
|
||||
LIBUS_SOCKET_DESCRIPTOR bsd_create_connect_socket_unix(const char *server_path, size_t len, int options, int *error) {
|
||||
struct sockaddr_un server_address;
|
||||
size_t addrlen = 0;
|
||||
int dirfd_linux_workaround_for_unix_path_len = -1;
|
||||
if (bsd_create_unix_socket_address(server_path, len, &dirfd_linux_workaround_for_unix_path_len, &server_address, &addrlen)) {
|
||||
if (bsd_create_unix_socket_address(server_path, len, &dirfd_linux_workaround_for_unix_path_len, &server_address, &addrlen, error)) {
|
||||
return LIBUS_SOCKET_ERROR;
|
||||
}
|
||||
|
||||
LIBUS_SOCKET_DESCRIPTOR fd = internal_bsd_create_connect_socket_unix(server_path, len, options, &server_address, addrlen);
|
||||
LIBUS_SOCKET_DESCRIPTOR fd = internal_bsd_create_connect_socket_unix(server_path, len, options, &server_address, addrlen, error);
|
||||
|
||||
#if defined(__linux__)
|
||||
if (dirfd_linux_workaround_for_unix_path_len != -1) {
|
||||
|
||||
@@ -416,8 +416,8 @@ struct us_listen_socket_t *us_socket_context_listen_unix(int ssl, struct us_sock
|
||||
return ls;
|
||||
}
|
||||
|
||||
struct us_socket_t* us_socket_context_connect_resolved_dns(struct us_socket_context_t *context, struct sockaddr_storage* addr, int options, int socket_ext_size) {
|
||||
LIBUS_SOCKET_DESCRIPTOR connect_socket_fd = bsd_create_connect_socket(addr, options);
|
||||
struct us_socket_t* us_socket_context_connect_resolved_dns(struct us_socket_context_t *context, struct sockaddr_storage* addr, int options, int socket_ext_size, int *error) {
|
||||
LIBUS_SOCKET_DESCRIPTOR connect_socket_fd = bsd_create_connect_socket(addr, options, error);
|
||||
if (connect_socket_fd == LIBUS_SOCKET_ERROR) {
|
||||
return NULL;
|
||||
}
|
||||
@@ -487,10 +487,10 @@ static bool try_parse_ip(const char *ip_str, int port, struct sockaddr_storage *
|
||||
return 0;
|
||||
}
|
||||
|
||||
void *us_socket_context_connect(int ssl, struct us_socket_context_t *context, const char *host, int port, int options, int socket_ext_size, int* has_dns_resolved) {
|
||||
void *us_socket_context_connect(int ssl, struct us_socket_context_t *context, const char *host, int port, int options, int socket_ext_size, int* has_dns_resolved, int *error) {
|
||||
#ifndef LIBUS_NO_SSL
|
||||
if (ssl == 1) {
|
||||
return us_internal_ssl_socket_context_connect((struct us_internal_ssl_socket_context_t *) context, host, port, options, socket_ext_size, has_dns_resolved);
|
||||
return us_internal_ssl_socket_context_connect((struct us_internal_ssl_socket_context_t *) context, host, port, options, socket_ext_size, has_dns_resolved, error);
|
||||
}
|
||||
#endif
|
||||
|
||||
@@ -500,7 +500,7 @@ void *us_socket_context_connect(int ssl, struct us_socket_context_t *context, co
|
||||
struct sockaddr_storage addr;
|
||||
if (try_parse_ip(host, port, &addr)) {
|
||||
*has_dns_resolved = 1;
|
||||
return us_socket_context_connect_resolved_dns(context, &addr, options, socket_ext_size);
|
||||
return us_socket_context_connect_resolved_dns(context, &addr, options, socket_ext_size, error);
|
||||
}
|
||||
|
||||
struct addrinfo_request* ai_req;
|
||||
@@ -519,7 +519,7 @@ void *us_socket_context_connect(int ssl, struct us_socket_context_t *context, co
|
||||
struct sockaddr_storage addr;
|
||||
init_addr_with_port(&result->entries->info, port, &addr);
|
||||
*has_dns_resolved = 1;
|
||||
struct us_socket_t *s = us_socket_context_connect_resolved_dns(context, &addr, options, socket_ext_size);
|
||||
struct us_socket_t *s = us_socket_context_connect_resolved_dns(context, &addr, options, socket_ext_size, error);
|
||||
Bun__addrinfo_freeRequest(ai_req, s == NULL);
|
||||
return s;
|
||||
}
|
||||
@@ -551,7 +551,7 @@ int start_connections(struct us_connecting_socket_t *c, int count) {
|
||||
for (; c->addrinfo_head != NULL && opened < count; c->addrinfo_head = c->addrinfo_head->ai_next) {
|
||||
struct sockaddr_storage addr;
|
||||
init_addr_with_port(c->addrinfo_head, c->port, &addr);
|
||||
LIBUS_SOCKET_DESCRIPTOR connect_socket_fd = bsd_create_connect_socket(&addr, c->options);
|
||||
LIBUS_SOCKET_DESCRIPTOR connect_socket_fd = bsd_create_connect_socket(&addr, c->options, NULL);
|
||||
if (connect_socket_fd == LIBUS_SOCKET_ERROR) {
|
||||
continue;
|
||||
}
|
||||
@@ -638,6 +638,8 @@ void us_internal_socket_after_open(struct us_socket_t *s, int error) {
|
||||
break;
|
||||
}
|
||||
default: {
|
||||
if (error == WSAENOTCONN) error = WSAECONNREFUSED;
|
||||
error = us_wsa_to_libuv_errno(error);
|
||||
break;
|
||||
}
|
||||
}
|
||||
@@ -716,14 +718,14 @@ void us_internal_socket_after_open(struct us_socket_t *s, int error) {
|
||||
}
|
||||
}
|
||||
|
||||
struct us_socket_t *us_socket_context_connect_unix(int ssl, struct us_socket_context_t *context, const char *server_path, size_t pathlen, int options, int socket_ext_size) {
|
||||
struct us_socket_t *us_socket_context_connect_unix(int ssl, struct us_socket_context_t *context, const char *server_path, size_t pathlen, int options, int socket_ext_size, int *error) {
|
||||
#ifndef LIBUS_NO_SSL
|
||||
if (ssl) {
|
||||
return (struct us_socket_t *) us_internal_ssl_socket_context_connect_unix((struct us_internal_ssl_socket_context_t *) context, server_path, pathlen, options, socket_ext_size);
|
||||
return (struct us_socket_t *) us_internal_ssl_socket_context_connect_unix((struct us_internal_ssl_socket_context_t *) context, server_path, pathlen, options, socket_ext_size, error);
|
||||
}
|
||||
#endif
|
||||
|
||||
LIBUS_SOCKET_DESCRIPTOR connect_socket_fd = bsd_create_connect_socket_unix(server_path, pathlen, options);
|
||||
LIBUS_SOCKET_DESCRIPTOR connect_socket_fd = bsd_create_connect_socket_unix(server_path, pathlen, options, error);
|
||||
if (connect_socket_fd == LIBUS_SOCKET_ERROR) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -141,8 +141,7 @@ int BIO_s_custom_write(BIO *bio, const char *data, int length) {
|
||||
|
||||
loop_ssl_data->last_write_was_msg_more =
|
||||
loop_ssl_data->msg_more || length == 16413;
|
||||
int written = us_socket_write(0, loop_ssl_data->ssl_socket, data, length,
|
||||
loop_ssl_data->last_write_was_msg_more);
|
||||
int written = us_socket_write(0, loop_ssl_data->ssl_socket, data, length, loop_ssl_data->last_write_was_msg_more, NULL);
|
||||
|
||||
BIO_clear_retry_flags(bio);
|
||||
if (!written) {
|
||||
@@ -1608,11 +1607,11 @@ static void us_internal_zero_ssl_data_for_connected_socket_before_onopen(struct
|
||||
// TODO does this need more changes?
|
||||
struct us_socket_t *us_internal_ssl_socket_context_connect(
|
||||
struct us_internal_ssl_socket_context_t *context, const char *host,
|
||||
int port, int options, int socket_ext_size, int* is_connecting) {
|
||||
int port, int options, int socket_ext_size, int* is_connecting, int *error) {
|
||||
struct us_internal_ssl_socket_t *s = (struct us_internal_ssl_socket_t *)us_socket_context_connect(
|
||||
2, &context->sc, host, port, options,
|
||||
sizeof(struct us_internal_ssl_socket_t) - sizeof(struct us_socket_t) +
|
||||
socket_ext_size, is_connecting);
|
||||
socket_ext_size, is_connecting, error);
|
||||
if (*is_connecting && s) {
|
||||
us_internal_zero_ssl_data_for_connected_socket_before_onopen(s);
|
||||
}
|
||||
@@ -1621,11 +1620,11 @@ struct us_socket_t *us_internal_ssl_socket_context_connect(
|
||||
}
|
||||
struct us_socket_t *us_internal_ssl_socket_context_connect_unix(
|
||||
struct us_internal_ssl_socket_context_t *context, const char *server_path,
|
||||
size_t pathlen, int options, int socket_ext_size) {
|
||||
size_t pathlen, int options, int socket_ext_size, int *error) {
|
||||
struct us_socket_t *s = (struct us_socket_t *)us_socket_context_connect_unix(
|
||||
0, &context->sc, server_path, pathlen, options,
|
||||
sizeof(struct us_internal_ssl_socket_t) - sizeof(struct us_socket_t) +
|
||||
socket_ext_size);
|
||||
socket_ext_size, error);
|
||||
if (s) {
|
||||
us_internal_zero_ssl_data_for_connected_socket_before_onopen((struct us_internal_ssl_socket_t*) s);
|
||||
}
|
||||
@@ -1747,7 +1746,7 @@ int us_internal_ssl_socket_raw_write(struct us_internal_ssl_socket_t *s,
|
||||
if (us_socket_is_closed(0, &s->s) || us_internal_ssl_socket_is_shut_down(s)) {
|
||||
return 0;
|
||||
}
|
||||
return us_socket_write(0, &s->s, data, length, msg_more);
|
||||
return us_socket_write(0, &s->s, data, length, msg_more, NULL);
|
||||
}
|
||||
|
||||
int us_internal_ssl_socket_write(struct us_internal_ssl_socket_t *s,
|
||||
|
||||
@@ -63,8 +63,9 @@ void us_internal_loop_update_pending_ready_polls(struct us_loop_t *loop,
|
||||
#endif
|
||||
|
||||
#ifdef _WIN32
|
||||
int us_wsa_to_libuv_errno(int);
|
||||
#define IS_EINTR(rc) (rc == SOCKET_ERROR && WSAGetLastError() == WSAEINTR)
|
||||
#define LIBUS_ERR WSAGetLastError()
|
||||
#define LIBUS_ERR us_wsa_to_libuv_errno(WSAGetLastError())
|
||||
#else
|
||||
#include <errno.h>
|
||||
#define IS_EINTR(rc) (rc == -1 && errno == EINTR)
|
||||
@@ -414,11 +415,11 @@ struct us_listen_socket_t *us_internal_ssl_socket_context_listen_unix(
|
||||
|
||||
struct us_socket_t *us_internal_ssl_socket_context_connect(
|
||||
us_internal_ssl_socket_context_r context, const char *host,
|
||||
int port, int options, int socket_ext_size, int* is_resolved);
|
||||
int port, int options, int socket_ext_size, int* is_resolved, int *error);
|
||||
|
||||
struct us_socket_t *us_internal_ssl_socket_context_connect_unix(
|
||||
us_internal_ssl_socket_context_r context, const char *server_path,
|
||||
size_t pathlen, int options, int socket_ext_size);
|
||||
size_t pathlen, int options, int socket_ext_size, int *error);
|
||||
|
||||
int us_internal_ssl_socket_write(us_internal_ssl_socket_r s,
|
||||
const char *data, int length, int msg_more);
|
||||
|
||||
@@ -25,6 +25,7 @@
|
||||
// here everything about the syscalls are inline-wrapped and included
|
||||
|
||||
#include "libusockets.h"
|
||||
#include "internal/internal.h"
|
||||
|
||||
#ifdef _WIN32
|
||||
#ifndef NOMINMAX
|
||||
@@ -210,11 +211,11 @@ ssize_t bsd_recv(LIBUS_SOCKET_DESCRIPTOR fd, void *buf, int length, int flags);
|
||||
#if !defined(_WIN32)
|
||||
ssize_t bsd_recvmsg(LIBUS_SOCKET_DESCRIPTOR fd, struct msghdr *msg, int flags);
|
||||
#endif
|
||||
ssize_t bsd_send(LIBUS_SOCKET_DESCRIPTOR fd, const char *buf, int length, int msg_more);
|
||||
ssize_t bsd_send(LIBUS_SOCKET_DESCRIPTOR fd, const char *buf, int length, int msg_more, int *error);
|
||||
#if !defined(_WIN32)
|
||||
ssize_t bsd_sendmsg(LIBUS_SOCKET_DESCRIPTOR fd, const struct msghdr *msg, int flags);
|
||||
#endif
|
||||
ssize_t bsd_write2(LIBUS_SOCKET_DESCRIPTOR fd, const char *header, int header_length, const char *payload, int payload_length);
|
||||
ssize_t bsd_write2(LIBUS_SOCKET_DESCRIPTOR fd, const char *header, int header_length, const char *payload, int payload_length, int *error);
|
||||
int bsd_would_block();
|
||||
|
||||
// return LIBUS_SOCKET_ERROR or the fd that represents listen socket
|
||||
@@ -228,9 +229,9 @@ LIBUS_SOCKET_DESCRIPTOR bsd_create_udp_socket(const char *host, int port, int op
|
||||
int bsd_connect_udp_socket(LIBUS_SOCKET_DESCRIPTOR fd, const char *host, int port);
|
||||
int bsd_disconnect_udp_socket(LIBUS_SOCKET_DESCRIPTOR fd);
|
||||
|
||||
LIBUS_SOCKET_DESCRIPTOR bsd_create_connect_socket(struct sockaddr_storage *addr, int options);
|
||||
LIBUS_SOCKET_DESCRIPTOR bsd_create_connect_socket(struct sockaddr_storage *addr, int options, int *error);
|
||||
|
||||
LIBUS_SOCKET_DESCRIPTOR bsd_create_connect_socket_unix(const char *server_path, size_t pathlen, int options);
|
||||
LIBUS_SOCKET_DESCRIPTOR bsd_create_connect_socket_unix(const char *server_path, size_t pathlen, int options, int *error);
|
||||
|
||||
#ifndef MSG_DONTWAIT
|
||||
#define MSG_DONTWAIT 0
|
||||
|
||||
@@ -327,10 +327,10 @@ void us_listen_socket_close(int ssl, struct us_listen_socket_t *ls) nonnull_fn_d
|
||||
per the happy eyeballs algorithm
|
||||
*/
|
||||
void *us_socket_context_connect(int ssl, struct us_socket_context_t * nonnull_arg context,
|
||||
const char *host, int port, int options, int socket_ext_size, int *is_connecting) __attribute__((nonnull(2)));
|
||||
const char *host, int port, int options, int socket_ext_size, int *is_connecting, int *error) __attribute__((nonnull(2)));
|
||||
|
||||
struct us_socket_t *us_socket_context_connect_unix(int ssl, us_socket_context_r context,
|
||||
const char *server_path, size_t pathlen, int options, int socket_ext_size) __attribute__((nonnull(2)));
|
||||
const char *server_path, size_t pathlen, int options, int socket_ext_size, int *error) __attribute__((nonnull(2)));
|
||||
|
||||
/* Is this socket established? Can be used to check if a connecting socket has fired the on_open event yet.
|
||||
* Can also be used to determine if a socket is a listen_socket or not, but you probably know that already. */
|
||||
@@ -421,10 +421,10 @@ void *us_socket_get_native_handle(int ssl, us_socket_r s) nonnull_fn_decl;
|
||||
/* Write up to length bytes of data. Returns actual bytes written.
|
||||
* Will call the on_writable callback of active socket context on failure to write everything off in one go.
|
||||
* Set hint msg_more if you have more immediate data to write. */
|
||||
int us_socket_write(int ssl, us_socket_r s, const char * nonnull_arg data, int length, int msg_more) nonnull_fn_decl;
|
||||
int us_socket_write(int ssl, us_socket_r s, const char * nonnull_arg data, int length, int msg_more, int *error);
|
||||
|
||||
/* Special path for non-SSL sockets. Used to send header and payload in one go. Works like us_socket_write. */
|
||||
int us_socket_write2(int ssl, us_socket_r s, const char *header, int header_length, const char *payload, int payload_length) nonnull_fn_decl;
|
||||
int us_socket_write2(int ssl, us_socket_r s, const char *header, int header_length, const char *payload, int payload_length, int *error);
|
||||
|
||||
/* Set a low precision, high performance timer on a socket. A socket can only have one single active timer
|
||||
* at any given point in time. Will remove any such pre set timer */
|
||||
|
||||
@@ -286,7 +286,7 @@ void us_internal_dispatch_ready_poll(struct us_poll_t *p, int error, int eof, in
|
||||
/* Both connect and listen sockets are semi-sockets
|
||||
* but they poll for different events */
|
||||
if (us_poll_events(p) == LIBUS_SOCKET_WRITABLE) {
|
||||
us_internal_socket_after_open((struct us_socket_t *) p, error || eof);
|
||||
us_internal_socket_after_open((struct us_socket_t *) p, (error || eof) ? ECONNREFUSED : 0);
|
||||
} else {
|
||||
struct us_listen_socket_t *listen_socket = (struct us_listen_socket_t *) p;
|
||||
struct bsd_addr_t addr;
|
||||
|
||||
@@ -289,12 +289,12 @@ struct us_socket_t *us_socket_pair(struct us_socket_context_t *ctx, int socket_e
|
||||
}
|
||||
|
||||
/* This is not available for SSL sockets as it makes no sense. */
|
||||
int us_socket_write2(int ssl, struct us_socket_t *s, const char *header, int header_length, const char *payload, int payload_length) {
|
||||
int us_socket_write2(int ssl, struct us_socket_t *s, const char *header, int header_length, const char *payload, int payload_length, int *error) {
|
||||
if (us_socket_is_closed(ssl, s) || us_socket_is_shut_down(ssl, s)) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
int written = bsd_write2(us_poll_fd(&s->p), header, header_length, payload, payload_length);
|
||||
int written = bsd_write2(us_poll_fd(&s->p), header, header_length, payload, payload_length, error);
|
||||
if (written != header_length + payload_length) {
|
||||
us_poll_change(&s->p, s->context->loop, LIBUS_SOCKET_READABLE | LIBUS_SOCKET_WRITABLE);
|
||||
}
|
||||
@@ -357,7 +357,7 @@ void *us_connecting_socket_get_native_handle(int ssl, struct us_connecting_socke
|
||||
return (void *) (uintptr_t) -1;
|
||||
}
|
||||
|
||||
int us_socket_write(int ssl, struct us_socket_t *s, const char *data, int length, int msg_more) {
|
||||
int us_socket_write(int ssl, struct us_socket_t *s, const char *data, int length, int msg_more, int *error) {
|
||||
#ifndef LIBUS_NO_SSL
|
||||
if (ssl) {
|
||||
return us_internal_ssl_socket_write((struct us_internal_ssl_socket_t *) s, data, length, msg_more);
|
||||
@@ -367,7 +367,7 @@ int us_socket_write(int ssl, struct us_socket_t *s, const char *data, int length
|
||||
return 0;
|
||||
}
|
||||
|
||||
int written = bsd_send(us_poll_fd(&s->p), data, length, msg_more);
|
||||
int written = bsd_send(us_poll_fd(&s->p), data, length, msg_more, error);
|
||||
if (written != length) {
|
||||
s->context->loop->data.last_write_failed = 1;
|
||||
us_poll_change(&s->p, s->context->loop, LIBUS_SOCKET_READABLE | LIBUS_SOCKET_WRITABLE);
|
||||
@@ -502,7 +502,7 @@ int us_socket_raw_write(int ssl, struct us_socket_t *s, const char *data, int le
|
||||
}
|
||||
#endif
|
||||
// non-TLS is always raw
|
||||
return us_socket_write(ssl, s, data, length, msg_more);
|
||||
return us_socket_write(ssl, s, data, length, msg_more, NULL);
|
||||
}
|
||||
|
||||
unsigned int us_get_remote_address_info(char *buf, struct us_socket_t *s, const char **dest, int *port, int *is_ipv6)
|
||||
|
||||
@@ -247,7 +247,7 @@ public:
|
||||
int max_flush_len = std::min(buffer_len, (size_t)INT_MAX);
|
||||
|
||||
/* Attempt to write data to the socket */
|
||||
int written = us_socket_write(SSL, (us_socket_t *) this, asyncSocketData->buffer.data(), max_flush_len, 0);
|
||||
int written = us_socket_write(SSL, (us_socket_t *) this, asyncSocketData->buffer.data(), max_flush_len, 0, NULL);
|
||||
total_written += written;
|
||||
|
||||
/* Check if we couldn't write the entire buffer */
|
||||
@@ -297,7 +297,7 @@ public:
|
||||
int max_flush_len = std::min(buffer_len, (size_t)INT_MAX);
|
||||
|
||||
/* Write off as much as we can */
|
||||
int written = us_socket_write(SSL, (us_socket_t *) this, asyncSocketData->buffer.data(), max_flush_len, /*nextLength != 0 | */length);
|
||||
int written = us_socket_write(SSL, (us_socket_t *) this, asyncSocketData->buffer.data(), max_flush_len, /*nextLength != 0 | */length, NULL);
|
||||
/* On failure return, otherwise continue down the function */
|
||||
if ((unsigned int) written < buffer_len) {
|
||||
/* Update buffering (todo: we can do better here if we keep track of what happens to this guy later on) */
|
||||
@@ -342,7 +342,7 @@ public:
|
||||
}
|
||||
} else {
|
||||
/* We are not corked */
|
||||
int written = us_socket_write(SSL, (us_socket_t *) this, src, length, nextLength != 0);
|
||||
int written = us_socket_write(SSL, (us_socket_t *) this, src, length, nextLength != 0, NULL);
|
||||
|
||||
/* Did we fail? */
|
||||
if (written < length) {
|
||||
|
||||
@@ -383,7 +383,7 @@ private:
|
||||
httpContextData->onClientError(SSL, s, result.parserError, data, length);
|
||||
}
|
||||
/* For errors, we only deliver them "at most once". We don't care if they get halfways delivered or not. */
|
||||
us_socket_write(SSL, s, httpErrorResponses[httpErrorStatusCode].data(), (int) httpErrorResponses[httpErrorStatusCode].length(), false);
|
||||
us_socket_write(SSL, s, httpErrorResponses[httpErrorStatusCode].data(), (int) httpErrorResponses[httpErrorStatusCode].length(), false, NULL);
|
||||
us_socket_shutdown(SSL, s);
|
||||
/* Close any socket on HTTP errors */
|
||||
us_socket_close(SSL, s, 0, nullptr);
|
||||
@@ -588,7 +588,7 @@ public:
|
||||
methods = getAllHttpMethods();
|
||||
} else {
|
||||
methods_buffer[0] = std::string(method);
|
||||
methods = {methods_buffer.data(), 1};
|
||||
methods = {methods_buffer.data(), 1};
|
||||
}
|
||||
|
||||
uint32_t priority = method == "*" ? httpContextData->currentRouter->LOW_PRIORITY : (upgrade ? httpContextData->currentRouter->HIGH_PRIORITY : httpContextData->currentRouter->MEDIUM_PRIORITY);
|
||||
|
||||
@@ -114,7 +114,7 @@ public:
|
||||
if (message.length() >= 16 * 1024 && !compress && !SSL && !webSocketData->subscriber && getBufferedAmount() == 0 && Super::getLoopData()->getCorkOffset() == 0) {
|
||||
char header[10];
|
||||
int header_length = (int) protocol::formatMessage<isServer>(header, "", 0, opCode, message.length(), compress, fin);
|
||||
int written = us_socket_write2(0, (struct us_socket_t *)this, header, header_length, message.data(), (int) message.length());
|
||||
int written = us_socket_write2(0, (struct us_socket_t *)this, header, header_length, message.data(), (int) message.length(), NULL);
|
||||
|
||||
if (written != header_length + (int) message.length()) {
|
||||
/* Buffer up backpressure */
|
||||
|
||||
@@ -2414,7 +2414,7 @@ pub const DNSResolver = struct {
|
||||
.result => |result| return result,
|
||||
.err => |err| {
|
||||
const system_error = JSC.SystemError{
|
||||
.errno = -1,
|
||||
.errno = @intFromEnum(bun.sys.SystemErrno.EPERM),
|
||||
.code = bun.String.static(err.code()),
|
||||
.message = bun.String.static(err.label()),
|
||||
};
|
||||
@@ -3120,7 +3120,7 @@ pub const DNSResolver = struct {
|
||||
defer syscall.deref();
|
||||
|
||||
const system_error = JSC.SystemError{
|
||||
.errno = -1,
|
||||
.errno = @intFromEnum(bun.sys.SystemErrno.EPERM),
|
||||
.code = bun.String.static(err.code()),
|
||||
.message = bun.String.static(err.label()),
|
||||
.syscall = syscall,
|
||||
|
||||
@@ -141,8 +141,7 @@ pub const Handlers = struct {
|
||||
handlers: *Handlers,
|
||||
|
||||
pub fn exit(this: *Scope) void {
|
||||
var vm = this.handlers.vm;
|
||||
defer vm.eventLoop().exit();
|
||||
this.handlers.vm.eventLoop().exit();
|
||||
this.handlers.markInactive();
|
||||
}
|
||||
};
|
||||
@@ -150,9 +149,7 @@ pub const Handlers = struct {
|
||||
pub fn enter(this: *Handlers) Scope {
|
||||
this.markActive();
|
||||
this.vm.eventLoop().enter();
|
||||
return .{
|
||||
.handlers = this,
|
||||
};
|
||||
return .{ .handlers = this };
|
||||
}
|
||||
|
||||
// corker: Corker = .{},
|
||||
@@ -776,8 +773,13 @@ pub const Listener = struct {
|
||||
break :brk socket_context.listenUnix(ssl_enabled, host, host.len, socket_flags, 8, &errno);
|
||||
},
|
||||
.fd => |fd| {
|
||||
_ = fd;
|
||||
return globalObject.ERR(.INVALID_ARG_VALUE, "Bun does not support listening on a file descriptor.", .{}).throw();
|
||||
return JSC.SystemError.throw(globalObject, .{
|
||||
.errno = @intFromEnum(bun.sys.SystemErrno.EINVAL),
|
||||
.code = .static("EINVAL"),
|
||||
.message = .static("Bun does not support listening on a file descriptor."),
|
||||
.syscall = .static("listen"),
|
||||
.fd = fd.uv(),
|
||||
});
|
||||
},
|
||||
}
|
||||
} orelse {
|
||||
@@ -1215,14 +1217,13 @@ pub const Listener = struct {
|
||||
true => uws.SocketContext.createSSLContext(uws.Loop.get(), @sizeOf(usize), ctx_opts, &create_err),
|
||||
false => uws.SocketContext.createNoSSLContext(uws.Loop.get(), @sizeOf(usize)),
|
||||
} orelse {
|
||||
const err = JSC.SystemError{
|
||||
handlers.unprotect();
|
||||
connection.deinit();
|
||||
return JSC.SystemError.throw(globalObject, .{
|
||||
.message = bun.String.static("Failed to connect"),
|
||||
.syscall = bun.String.static("connect"),
|
||||
.code = if (port == null) bun.String.static("ENOENT") else bun.String.static("ECONNREFUSED"),
|
||||
};
|
||||
handlers.unprotect();
|
||||
connection.deinit();
|
||||
return globalObject.throwValue(err.toErrorInstance(globalObject));
|
||||
});
|
||||
};
|
||||
|
||||
if (ssl_enabled) {
|
||||
@@ -1274,8 +1275,11 @@ pub const Listener = struct {
|
||||
socket.ref();
|
||||
SocketType.js.dataSetCached(socket.getThisValue(globalObject), globalObject, default_data);
|
||||
socket.flags.allow_half_open = socket_config.allowHalfOpen;
|
||||
socket.doConnect(connection) catch {
|
||||
socket.handleConnectError(@intFromEnum(if (port == null) bun.sys.SystemErrno.ENOENT else bun.sys.SystemErrno.ECONNREFUSED));
|
||||
var error_: i32 = 0;
|
||||
socket.doConnect(connection, &error_) catch {
|
||||
bun.assert(error_ > 0);
|
||||
if (Environment.isWindows and port == null and error_ == bun.sys.SystemErrno.ECONNREFUSED.to_uv_errno()) error_ = bun.sys.SystemErrno.ENOENT.to_uv_errno(); //TODO: use better WSA api
|
||||
socket.handleConnectError(error_);
|
||||
return promise_value;
|
||||
};
|
||||
|
||||
@@ -1465,7 +1469,7 @@ fn NewSocket(comptime ssl: bool) type {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn doConnect(this: *This, connection: Listener.UnixOrHost) !void {
|
||||
pub fn doConnect(this: *This, connection: Listener.UnixOrHost, error_: ?*i32) !void {
|
||||
bun.assert(this.socket_context != null);
|
||||
this.ref();
|
||||
errdefer this.deref();
|
||||
@@ -1478,6 +1482,7 @@ fn NewSocket(comptime ssl: bool) type {
|
||||
this.socket_context.?,
|
||||
this,
|
||||
this.flags.allow_half_open,
|
||||
error_,
|
||||
);
|
||||
},
|
||||
.unix => |u| {
|
||||
@@ -1486,10 +1491,14 @@ fn NewSocket(comptime ssl: bool) type {
|
||||
this.socket_context.?,
|
||||
this,
|
||||
this.flags.allow_half_open,
|
||||
error_,
|
||||
);
|
||||
},
|
||||
.fd => |f| {
|
||||
const socket = This.Socket.fromFd(this.socket_context.?, f, This, this, null, false) orelse return error.ConnectionFailed;
|
||||
const socket = This.Socket.fromFd(this.socket_context.?, f, This, this, null, false) orelse {
|
||||
if (error_) |err| err.* = bun.sys.SystemErrno.ENOENT.to_uv_errno();
|
||||
return error.ConnectionFailed;
|
||||
};
|
||||
this.onOpen(socket);
|
||||
},
|
||||
}
|
||||
@@ -1568,8 +1577,10 @@ fn NewSocket(comptime ssl: bool) type {
|
||||
if (vm.isShuttingDown()) {
|
||||
return;
|
||||
}
|
||||
vm.eventLoop().enter();
|
||||
defer vm.eventLoop().exit();
|
||||
// the handlers must be kept alive for the duration of the function call
|
||||
// that way if we need to call the error handler, we can
|
||||
var scope = handlers.enter();
|
||||
defer scope.exit();
|
||||
const globalObject = handlers.globalObject;
|
||||
const this_value = this.getThisValue(globalObject);
|
||||
_ = handlers.callErrorHandler(this_value, &.{ this_value, err_value });
|
||||
@@ -1589,13 +1600,15 @@ fn NewSocket(comptime ssl: bool) type {
|
||||
}
|
||||
this.ref();
|
||||
defer this.deref();
|
||||
this.internalFlush();
|
||||
this.internalFlush() catch return;
|
||||
log("onWritable buffered_data_for_node_net {d}", .{this.buffered_data_for_node_net.len});
|
||||
// is not writable if we have buffered data or if we are already detached
|
||||
if (this.buffered_data_for_node_net.len > 0 or this.socket.isDetached()) return;
|
||||
|
||||
vm.eventLoop().enter();
|
||||
defer vm.eventLoop().exit();
|
||||
// the handlers must be kept alive for the duration of the function call
|
||||
// that way if we need to call the error handler, we can
|
||||
var scope = handlers.enter();
|
||||
defer scope.exit();
|
||||
|
||||
const globalObject = handlers.globalObject;
|
||||
const this_value = this.getThisValue(globalObject);
|
||||
@@ -1647,23 +1660,22 @@ fn NewSocket(comptime ssl: bool) type {
|
||||
}
|
||||
|
||||
bun.assert(errno >= 0);
|
||||
var errno_: c_int = if (errno == @intFromEnum(bun.sys.SystemErrno.ENOENT)) @intFromEnum(bun.sys.SystemErrno.ENOENT) else @intFromEnum(bun.sys.SystemErrno.ECONNREFUSED);
|
||||
const code_ = if (errno == @intFromEnum(bun.sys.SystemErrno.ENOENT)) bun.String.static("ENOENT") else bun.String.static("ECONNREFUSED");
|
||||
if (Environment.isWindows and errno_ == @intFromEnum(bun.sys.SystemErrno.ENOENT)) errno_ = @intFromEnum(bun.sys.SystemErrno.UV_ENOENT);
|
||||
if (Environment.isWindows and errno_ == @intFromEnum(bun.sys.SystemErrno.ECONNREFUSED)) errno_ = @intFromEnum(bun.sys.SystemErrno.UV_ECONNREFUSED);
|
||||
const errno_: c_uint = @intCast(errno);
|
||||
const code_ = bun.String.static(@tagName(@as(bun.sys.SystemErrno, @enumFromInt(errno))));
|
||||
|
||||
const callback = handlers.onConnectError;
|
||||
const globalObject = handlers.globalObject;
|
||||
const err = JSC.SystemError{
|
||||
.errno = -errno_,
|
||||
const err_value = JSC.SystemError.createJS(globalObject, .{
|
||||
.errno = errno_,
|
||||
.message = bun.String.static("Failed to connect"),
|
||||
.syscall = bun.String.static("connect"),
|
||||
.code = code_,
|
||||
};
|
||||
vm.eventLoop().enter();
|
||||
defer {
|
||||
vm.eventLoop().exit();
|
||||
}
|
||||
});
|
||||
|
||||
// the handlers must be kept alive for the duration of the function call
|
||||
// that way if we need to call the error handler, we can
|
||||
var scope = handlers.enter();
|
||||
defer scope.exit();
|
||||
|
||||
if (callback == .zero) {
|
||||
if (handlers.promise.trySwap()) |promise| {
|
||||
@@ -1674,7 +1686,6 @@ fn NewSocket(comptime ssl: bool) type {
|
||||
this.has_pending_activity.store(false, .release);
|
||||
|
||||
// reject the promise on connect() error
|
||||
const err_value = err.toErrorInstance(globalObject);
|
||||
promise.asPromise().?.reject(globalObject, err_value);
|
||||
}
|
||||
|
||||
@@ -1685,11 +1696,7 @@ fn NewSocket(comptime ssl: bool) type {
|
||||
this.this_value = .zero;
|
||||
this.has_pending_activity.store(false, .release);
|
||||
|
||||
const err_value = err.toErrorInstance(globalObject);
|
||||
const result = callback.call(globalObject, this_value, &[_]JSValue{
|
||||
this_value,
|
||||
err_value,
|
||||
}) catch |e| globalObject.takeException(e);
|
||||
const result = callback.call(globalObject, this_value, &.{ this_value, err_value }) catch |e| globalObject.takeException(e);
|
||||
|
||||
if (result.toError()) |err_val| {
|
||||
if (handlers.rejectPromise(err_val)) return;
|
||||
@@ -1698,8 +1705,7 @@ fn NewSocket(comptime ssl: bool) type {
|
||||
// They've defined a `connectError` callback
|
||||
// The error is effectively handled, but we should still reject the promise.
|
||||
var promise = val.asPromise().?;
|
||||
const err_ = err.toErrorInstance(globalObject);
|
||||
promise.rejectAsHandled(globalObject, err_);
|
||||
promise.rejectAsHandled(globalObject, err_value);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1812,10 +1818,11 @@ fn NewSocket(comptime ssl: bool) type {
|
||||
} else {
|
||||
if (callback == .zero) return;
|
||||
}
|
||||
const vm = handlers.vm;
|
||||
vm.eventLoop().enter();
|
||||
defer vm.eventLoop().exit();
|
||||
const result = callback.call(globalObject, this_value, &[_]JSValue{this_value}) catch |err| globalObject.takeException(err);
|
||||
// the handlers must be kept alive for the duration of the function call
|
||||
// that way if we need to call the error handler, we can
|
||||
var scope = handlers.enter();
|
||||
defer scope.exit();
|
||||
const result = callback.call(globalObject, this_value, &.{this_value}) catch |err| globalObject.takeException(err);
|
||||
|
||||
if (result.toError()) |err| {
|
||||
defer this.markInactive();
|
||||
@@ -1911,7 +1918,7 @@ fn NewSocket(comptime ssl: bool) type {
|
||||
// open callback only have 1 parameters and its the socket
|
||||
// you should use getAuthorizationError and authorized getter to get those values in this case
|
||||
if (is_open) {
|
||||
result = callback.call(globalObject, this_value, &[_]JSValue{this_value}) catch |err| globalObject.takeException(err);
|
||||
result = callback.call(globalObject, this_value, &.{this_value}) catch |err| globalObject.takeException(err);
|
||||
|
||||
// only call onOpen once for clients
|
||||
if (!handlers.is_server) {
|
||||
@@ -1928,7 +1935,7 @@ fn NewSocket(comptime ssl: bool) type {
|
||||
else
|
||||
ssl_error.toJS(globalObject);
|
||||
|
||||
result = callback.call(globalObject, this_value, &[_]JSValue{
|
||||
result = callback.call(globalObject, this_value, &.{
|
||||
this_value,
|
||||
JSValue.jsBoolean(authorized),
|
||||
authorization_error,
|
||||
@@ -1978,7 +1985,7 @@ fn NewSocket(comptime ssl: bool) type {
|
||||
js_error = bun.sys.Error.fromCodeInt(err, .read).toJSC(globalObject);
|
||||
}
|
||||
|
||||
_ = callback.call(globalObject, this_value, &[_]JSValue{
|
||||
_ = callback.call(globalObject, this_value, &.{
|
||||
this_value,
|
||||
js_error,
|
||||
}) catch |e| {
|
||||
@@ -2009,7 +2016,7 @@ fn NewSocket(comptime ssl: bool) type {
|
||||
defer scope.exit();
|
||||
|
||||
// const encoding = handlers.encoding;
|
||||
_ = callback.call(globalObject, this_value, &[_]JSValue{
|
||||
_ = callback.call(globalObject, this_value, &.{
|
||||
this_value,
|
||||
output_value,
|
||||
}) catch |err| {
|
||||
@@ -2223,18 +2230,25 @@ fn NewSocket(comptime ssl: bool) type {
|
||||
pub fn writeBuffered(this: *This, globalObject: *JSC.JSGlobalObject, callframe: *JSC.CallFrame) bun.JSError!JSValue {
|
||||
if (this.socket.isDetached()) {
|
||||
this.buffered_data_for_node_net.deinitWithAllocator(bun.default_allocator);
|
||||
return JSValue.jsBoolean(false);
|
||||
// should we separate unattached and detached?
|
||||
return JSC.SystemError.throw(globalObject, .{
|
||||
.errno = @intFromEnum(bun.sys.SystemErrno.EBADF),
|
||||
.code = .static("EBADF"),
|
||||
.message = .static("write EBADF"),
|
||||
.syscall = .static("write"),
|
||||
});
|
||||
}
|
||||
|
||||
const args = callframe.argumentsUndef(2);
|
||||
const args = callframe.argumentsAsArray(2);
|
||||
|
||||
return switch (this.writeOrEndBuffered(globalObject, args.ptr[0], args.ptr[1], false)) {
|
||||
return switch (this.writeOrEndBuffered(globalObject, args[0], args[1], false)) {
|
||||
.fail => .zero,
|
||||
.success => |result| if (@max(result.wrote, 0) == result.total) .true else .false,
|
||||
};
|
||||
}
|
||||
|
||||
pub fn endBuffered(this: *This, globalObject: *JSC.JSGlobalObject, callframe: *JSC.CallFrame) bun.JSError!JSValue {
|
||||
JSC.markBinding(@src());
|
||||
if (this.socket.isDetached()) {
|
||||
this.buffered_data_for_node_net.deinitWithAllocator(bun.default_allocator);
|
||||
return JSValue.jsBoolean(false);
|
||||
@@ -2247,7 +2261,7 @@ fn NewSocket(comptime ssl: bool) type {
|
||||
.fail => .zero,
|
||||
.success => |result| brk: {
|
||||
if (result.wrote == result.total) {
|
||||
this.internalFlush();
|
||||
this.internalFlush() catch return .jsBoolean(false);
|
||||
}
|
||||
|
||||
break :brk JSValue.jsBoolean(@as(usize, @max(result.wrote, 0)) == result.total);
|
||||
@@ -2315,7 +2329,7 @@ fn NewSocket(comptime ssl: bool) type {
|
||||
if (comptime !ssl and Environment.isPosix) {
|
||||
// fast-ish path: use writev() to avoid cloning to another buffer.
|
||||
if (this.socket.socket == .connected and buffer.slice().len > 0) {
|
||||
const rc = this.socket.socket.connected.write2(ssl, this.buffered_data_for_node_net.slice(), buffer.slice());
|
||||
const rc = this.socket.socket.connected.write2(ssl, this.buffered_data_for_node_net.slice(), buffer.slice(), null);
|
||||
const written: usize = @intCast(@max(rc, 0));
|
||||
const leftover = total_to_write -| written;
|
||||
if (leftover == 0) {
|
||||
@@ -2525,19 +2539,25 @@ fn NewSocket(comptime ssl: bool) type {
|
||||
return this.flags.is_active and this.flags.end_after_flush and !this.flags.empty_packet_pending and this.buffered_data_for_node_net.len == 0;
|
||||
}
|
||||
|
||||
fn internalFlush(this: *This) void {
|
||||
fn internalFlush(this: *This) error{CalledOnError}!void {
|
||||
if (this.buffered_data_for_node_net.len > 0) {
|
||||
const written: usize = @intCast(@max(this.socket.write(this.buffered_data_for_node_net.slice(), false), 0));
|
||||
this.bytes_written += written;
|
||||
if (written > 0) {
|
||||
if (this.buffered_data_for_node_net.len > written) {
|
||||
const remaining = this.buffered_data_for_node_net.slice()[written..];
|
||||
_ = bun.c.memmove(this.buffered_data_for_node_net.ptr, remaining.ptr, remaining.len);
|
||||
this.buffered_data_for_node_net.len = @truncate(remaining.len);
|
||||
} else {
|
||||
this.buffered_data_for_node_net.deinitWithAllocator(bun.default_allocator);
|
||||
this.buffered_data_for_node_net = .{};
|
||||
}
|
||||
switch (this.socket.writeMaybe(this.buffered_data_for_node_net.slice(), false)) {
|
||||
.result => |written_| {
|
||||
const written: usize = @intCast(written_);
|
||||
this.bytes_written += written;
|
||||
if (this.buffered_data_for_node_net.len > written) {
|
||||
const remaining = this.buffered_data_for_node_net.slice()[written..];
|
||||
_ = bun.c.memmove(this.buffered_data_for_node_net.ptr, remaining.ptr, remaining.len);
|
||||
this.buffered_data_for_node_net.len = @truncate(remaining.len);
|
||||
} else {
|
||||
this.buffered_data_for_node_net.deinitWithAllocator(bun.default_allocator);
|
||||
this.buffered_data_for_node_net = .{};
|
||||
}
|
||||
},
|
||||
.err => |err| {
|
||||
this.handleError(err.toSystemError().toErrorInstance(this.handlers.globalObject));
|
||||
return error.CalledOnError;
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2551,7 +2571,7 @@ fn NewSocket(comptime ssl: bool) type {
|
||||
|
||||
pub fn flush(this: *This, _: *JSC.JSGlobalObject, _: *JSC.CallFrame) bun.JSError!JSValue {
|
||||
JSC.markBinding(@src());
|
||||
this.internalFlush();
|
||||
this.internalFlush() catch return .js_undefined;
|
||||
return .js_undefined;
|
||||
}
|
||||
|
||||
@@ -2599,7 +2619,7 @@ fn NewSocket(comptime ssl: bool) type {
|
||||
.fail => .zero,
|
||||
.success => |result| brk: {
|
||||
if (result.wrote == result.total) {
|
||||
this.internalFlush();
|
||||
this.internalFlush() catch return .jsNumber(0);
|
||||
}
|
||||
break :brk JSValue.jsNumber(result.wrote);
|
||||
},
|
||||
@@ -3731,7 +3751,7 @@ pub const DuplexUpgradeContext = struct {
|
||||
}
|
||||
} else {
|
||||
if (this.tls) |tls| {
|
||||
tls.handleConnectError(@intFromEnum(bun.sys.SystemErrno.ECONNREFUSED));
|
||||
tls.handleConnectError(bun.sys.SystemErrno.ECONNREFUSED.to_uv_errno());
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -3764,7 +3784,7 @@ pub const DuplexUpgradeContext = struct {
|
||||
bun.outOfMemory();
|
||||
},
|
||||
else => {
|
||||
const errno = @intFromEnum(bun.sys.SystemErrno.ECONNREFUSED);
|
||||
const errno = bun.sys.SystemErrno.ECONNREFUSED.to_uv_errno();
|
||||
if (this.tls) |tls| {
|
||||
const socket = TLSSocket.Socket.fromDuplex(&this.upgrade);
|
||||
|
||||
@@ -4132,10 +4152,10 @@ pub const WindowsNamedPipeContext = if (Environment.isWindows) struct {
|
||||
errdefer {
|
||||
switch (socket) {
|
||||
.tls => |tls| {
|
||||
tls.handleConnectError(@intFromEnum(bun.sys.SystemErrno.ENOENT));
|
||||
tls.handleConnectError(bun.sys.SystemErrno.ENOENT.to_uv_errno());
|
||||
},
|
||||
.tcp => |tcp| {
|
||||
tcp.handleConnectError(@intFromEnum(bun.sys.SystemErrno.ENOENT));
|
||||
tcp.handleConnectError(bun.sys.SystemErrno.ENOENT.to_uv_errno());
|
||||
},
|
||||
.none => {},
|
||||
}
|
||||
@@ -4152,10 +4172,10 @@ pub const WindowsNamedPipeContext = if (Environment.isWindows) struct {
|
||||
errdefer {
|
||||
switch (socket) {
|
||||
.tls => |tls| {
|
||||
tls.handleConnectError(@intFromEnum(bun.sys.SystemErrno.ENOENT));
|
||||
tls.handleConnectError(bun.sys.SystemErrno.ENOENT.to_uv_errno());
|
||||
},
|
||||
.tcp => |tcp| {
|
||||
tcp.handleConnectError(@intFromEnum(bun.sys.SystemErrno.ENOENT));
|
||||
tcp.handleConnectError(bun.sys.SystemErrno.ENOENT.to_uv_errno());
|
||||
},
|
||||
.none => {},
|
||||
}
|
||||
|
||||
@@ -2277,7 +2277,7 @@ pub fn spawnMaybeSync(
|
||||
else
|
||||
"";
|
||||
var systemerror = bun.sys.Error.fromCode(if (err == error.EMFILE) .MFILE else .NFILE, .posix_spawn).withPath(display_path).toSystemError();
|
||||
systemerror.errno = if (err == error.EMFILE) -bun.sys.UV_E.MFILE else -bun.sys.UV_E.NFILE;
|
||||
systemerror.errno = if (err == error.EMFILE) bun.sys.UV_E.MFILE else bun.sys.UV_E.NFILE;
|
||||
return globalThis.throwValue(systemerror.toErrorInstance(globalThis));
|
||||
},
|
||||
else => {
|
||||
@@ -2295,7 +2295,7 @@ pub fn spawnMaybeSync(
|
||||
"";
|
||||
if (display_path.len > 0) {
|
||||
var systemerror = err.withPath(display_path).toSystemError();
|
||||
if (errno == .NOENT) systemerror.errno = -bun.sys.UV_E.NOENT;
|
||||
if (errno == .NOENT) systemerror.errno = bun.sys.UV_E.NOENT;
|
||||
return globalThis.throwValue(systemerror.toErrorInstance(globalThis));
|
||||
}
|
||||
},
|
||||
@@ -2391,12 +2391,7 @@ pub fn spawnMaybeSync(
|
||||
var posix_ipc_info: if (Environment.isPosix) IPC.Socket else void = undefined;
|
||||
if (Environment.isPosix and !is_sync) {
|
||||
if (maybe_ipc_mode) |mode| {
|
||||
if (uws.us_socket_t.fromFd(
|
||||
jsc_vm.rareData().spawnIPCContext(jsc_vm),
|
||||
@sizeOf(*IPC.SendQueue),
|
||||
posix_ipc_fd.cast(),
|
||||
1,
|
||||
)) |socket| {
|
||||
if (uws.us_socket_t.fromFd(jsc_vm.rareData().spawnIPCContext(jsc_vm), @sizeOf(*IPC.SendQueue), posix_ipc_fd.cast(), 1)) |socket| {
|
||||
subprocess.ipc_data = .init(mode, .{ .subprocess = subprocess }, .uninitialized);
|
||||
posix_ipc_info = IPC.Socket.from(socket);
|
||||
}
|
||||
@@ -2600,13 +2595,12 @@ pub fn spawnMaybeSync(
|
||||
}
|
||||
|
||||
fn throwCommandNotFound(globalThis: *JSC.JSGlobalObject, command: []const u8) bun.JSError {
|
||||
const err = JSC.SystemError{
|
||||
return JSC.SystemError.throw(globalThis, .{
|
||||
.message = bun.String.createFormat("Executable not found in $PATH: \"{s}\"", .{command}) catch bun.outOfMemory(),
|
||||
.code = bun.String.static("ENOENT"),
|
||||
.errno = -bun.sys.UV_E.NOENT,
|
||||
.errno = bun.sys.UV_E.NOENT,
|
||||
.path = bun.String.createUTF8(command),
|
||||
};
|
||||
return globalThis.throwValue(err.toErrorInstance(globalThis));
|
||||
});
|
||||
}
|
||||
|
||||
const node_cluster_binding = @import("./../../node/node_cluster_binding.zig");
|
||||
|
||||
@@ -333,12 +333,11 @@ pub const UDPSocket = struct {
|
||||
defer this.deinit();
|
||||
if (err != 0) {
|
||||
const code = @tagName(bun.sys.SystemErrno.init(@as(c_int, @intCast(err))).?);
|
||||
const sys_err = JSC.SystemError{
|
||||
.errno = err,
|
||||
const error_value = JSC.SystemError.createJS(globalThis, .{
|
||||
.errno = @intCast(err),
|
||||
.code = bun.String.static(code),
|
||||
.message = bun.String.createFormat("bind {s} {s}", .{ code, config.hostname }) catch bun.outOfMemory(),
|
||||
};
|
||||
const error_value = sys_err.toErrorInstance(globalThis);
|
||||
});
|
||||
error_value.put(globalThis, "address", bun.String.createUTF8ForJS(globalThis, config.hostname));
|
||||
return globalThis.throwValue(error_value);
|
||||
}
|
||||
|
||||
@@ -493,18 +493,16 @@ pub const HTMLRewriter = struct {
|
||||
defer sink.deref();
|
||||
return switch (buffering_error) {
|
||||
error.StreamAlreadyUsed => {
|
||||
var err = JSC.SystemError{
|
||||
return JSC.SystemError.createJS(sink.global, .{
|
||||
.code = bun.String.static("ERR_STREAM_ALREADY_FINISHED"),
|
||||
.message = bun.String.static("Stream already used, please create a new one"),
|
||||
};
|
||||
return err.toErrorInstance(sink.global);
|
||||
});
|
||||
},
|
||||
else => {
|
||||
var err = JSC.SystemError{
|
||||
return JSC.SystemError.createJS(sink.global, .{
|
||||
.code = bun.String.static("ERR_STREAM_CANNOT_PIPE"),
|
||||
.message = bun.String.static("Failed to pipe stream"),
|
||||
};
|
||||
return err.toErrorInstance(sink.global);
|
||||
});
|
||||
},
|
||||
};
|
||||
};
|
||||
|
||||
@@ -1738,7 +1738,7 @@ JSC_DEFINE_HOST_FUNCTION(Bun::jsFunctionMakeErrorWithCode, (JSC::JSGlobalObject
|
||||
}
|
||||
case 2: {
|
||||
JSValue arg0 = callFrame->argument(1);
|
||||
// ["foo", "bar", "baz"] -> 'The "foo", "bar", or "baz" argument must be specified'
|
||||
// ["foo", "bar", "baz"] -> 'The "foo" or "bar" or "baz" argument must be specified'
|
||||
if (auto* arr = jsDynamicCast<JSC::JSArray*>(arg0)) {
|
||||
ASSERT(arr->length() > 0);
|
||||
WTF::StringBuilder builder;
|
||||
@@ -1746,7 +1746,7 @@ JSC_DEFINE_HOST_FUNCTION(Bun::jsFunctionMakeErrorWithCode, (JSC::JSGlobalObject
|
||||
for (unsigned i = 0, length = arr->length(); i < length; i++) {
|
||||
JSValue index = arr->getIndex(globalObject, i);
|
||||
RETURN_IF_EXCEPTION(scope, {});
|
||||
if (i == length - 1) builder.append("or "_s);
|
||||
if (i > 0) builder.append("or "_s);
|
||||
builder.append('"');
|
||||
auto* jsString = index.toString(globalObject);
|
||||
RETURN_IF_EXCEPTION(scope, {});
|
||||
@@ -1754,7 +1754,6 @@ JSC_DEFINE_HOST_FUNCTION(Bun::jsFunctionMakeErrorWithCode, (JSC::JSGlobalObject
|
||||
RETURN_IF_EXCEPTION(scope, {});
|
||||
builder.append(str);
|
||||
builder.append('"');
|
||||
if (i != length - 1) builder.append(',');
|
||||
builder.append(' ');
|
||||
}
|
||||
builder.append("argument must be specified"_s);
|
||||
|
||||
@@ -6,7 +6,7 @@ const JSValue = JSC.JSValue;
|
||||
const JSGlobalObject = JSC.JSGlobalObject;
|
||||
|
||||
pub const SystemError = extern struct {
|
||||
errno: c_int = 0,
|
||||
errno: c_uint = 0,
|
||||
/// label for errno
|
||||
code: String = .empty,
|
||||
message: String = .empty,
|
||||
@@ -29,7 +29,7 @@ pub const SystemError = extern struct {
|
||||
|
||||
pub fn getErrno(this: *const SystemError) bun.sys.E {
|
||||
// The inverse in bun.sys.Error.toSystemError()
|
||||
return @enumFromInt(this.errno * -1);
|
||||
return @enumFromInt(this.errno);
|
||||
}
|
||||
|
||||
pub fn deref(this: *const SystemError) void {
|
||||
@@ -81,6 +81,14 @@ pub const SystemError = extern struct {
|
||||
return SystemError__toErrorInstanceWithInfoObject(this, global);
|
||||
}
|
||||
|
||||
pub fn createJS(globalThis: *JSGlobalObject, literal_init: SystemError) JSValue {
|
||||
return literal_init.toErrorInstance(globalThis);
|
||||
}
|
||||
|
||||
pub fn throw(globalThis: *JSGlobalObject, literal_init: SystemError) bun.JSError {
|
||||
return globalThis.throwValue(literal_init.toErrorInstance(globalThis));
|
||||
}
|
||||
|
||||
pub fn format(self: SystemError, comptime _: []const u8, _: std.fmt.FormatOptions, writer: anytype) !void {
|
||||
if (!self.path.isEmpty()) {
|
||||
// TODO: remove this hardcoding
|
||||
|
||||
@@ -2134,7 +2134,7 @@ JSC::EncodedJSValue SystemError__toErrorInstance(const SystemError* arg0, JSC::J
|
||||
result->putDirect(vm, names.hostnamePublicName(), hostname, JSC::PropertyAttribute::DontDelete | 0);
|
||||
}
|
||||
|
||||
result->putDirect(vm, names.errnoPublicName(), JSC::JSValue(err.errno_), JSC::PropertyAttribute::DontDelete | 0);
|
||||
result->putDirect(vm, names.errnoPublicName(), JSC::JSValue(-err.errno_), JSC::PropertyAttribute::DontDelete | 0);
|
||||
|
||||
RETURN_IF_EXCEPTION(scope, {});
|
||||
scope.release();
|
||||
@@ -2177,8 +2177,8 @@ JSC::EncodedJSValue SystemError__toErrorInstanceWithInfoObject(const SystemError
|
||||
info->putDirect(vm, clientData->builtinNames().codePublicName(), jsString(vm, codeString), JSC::PropertyAttribute::DontDelete | 0);
|
||||
info->putDirect(vm, vm.propertyNames->message, jsString(vm, messageString), JSC::PropertyAttribute::DontDelete | 0);
|
||||
|
||||
info->putDirect(vm, clientData->builtinNames().errnoPublicName(), jsNumber(err.errno_), JSC::PropertyAttribute::DontDelete | 0);
|
||||
result->putDirect(vm, clientData->builtinNames().errnoPublicName(), JSC::JSValue(err.errno_), JSC::PropertyAttribute::DontDelete | 0);
|
||||
info->putDirect(vm, clientData->builtinNames().errnoPublicName(), jsNumber(-err.errno_), JSC::PropertyAttribute::DontDelete | 0);
|
||||
result->putDirect(vm, clientData->builtinNames().errnoPublicName(), JSC::JSValue(-err.errno_), JSC::PropertyAttribute::DontDelete | 0);
|
||||
|
||||
RELEASE_AND_RETURN(scope, JSC::JSValue::encode(JSC::JSValue(result)));
|
||||
}
|
||||
|
||||
@@ -53,11 +53,10 @@ pub fn cpus(global: *JSC.JSGlobalObject) bun.JSError!JSC.JSValue {
|
||||
};
|
||||
|
||||
return cpusImpl(global) catch {
|
||||
const err = JSC.SystemError{
|
||||
return JSC.SystemError.throw(global, .{
|
||||
.message = bun.String.static("Failed to get CPU information"),
|
||||
.code = bun.String.static(@tagName(JSC.Node.ErrorCode.ERR_SYSTEM_ERROR)),
|
||||
};
|
||||
return global.throwValue(err.toErrorInstance(global));
|
||||
});
|
||||
};
|
||||
}
|
||||
|
||||
@@ -302,8 +301,8 @@ pub fn getPriority(global: *JSC.JSGlobalObject, pid: i32) bun.JSError!i32 {
|
||||
.message = bun.String.static("no such process"),
|
||||
.code = bun.String.static("ESRCH"),
|
||||
.errno = comptime switch (bun.Environment.os) {
|
||||
else => -@as(c_int, @intFromEnum(std.posix.E.SRCH)),
|
||||
.windows => libuv.UV_ESRCH,
|
||||
else => @intFromEnum(std.posix.E.SRCH),
|
||||
.windows => -libuv.UV_ESRCH,
|
||||
},
|
||||
.syscall = bun.String.static("uv_os_getpriority"),
|
||||
};
|
||||
@@ -471,14 +470,12 @@ fn networkInterfacesPosix(globalThis: *JSC.JSGlobalObject) bun.JSError!JSC.JSVal
|
||||
var interface_start: ?*c.ifaddrs = null;
|
||||
const rc = c.getifaddrs(&interface_start);
|
||||
if (rc != 0) {
|
||||
const err = JSC.SystemError{
|
||||
return JSC.SystemError.throw(globalThis, .{
|
||||
.message = bun.String.static("A system error occurred: getifaddrs returned an error"),
|
||||
.code = bun.String.static("ERR_SYSTEM_ERROR"),
|
||||
.errno = @intFromEnum(std.posix.errno(rc)),
|
||||
.syscall = bun.String.static("getifaddrs"),
|
||||
};
|
||||
|
||||
return globalThis.throwValue(err.toErrorInstance(globalThis));
|
||||
});
|
||||
}
|
||||
defer c.freeifaddrs(interface_start);
|
||||
|
||||
@@ -653,14 +650,13 @@ fn networkInterfacesWindows(globalThis: *JSC.JSGlobalObject) bun.JSError!JSC.JSV
|
||||
var count: c_int = undefined;
|
||||
const err = libuv.uv_interface_addresses(&ifaces, &count);
|
||||
if (err != 0) {
|
||||
const sys_err = JSC.SystemError{
|
||||
return JSC.SystemError.throw(globalThis, .{
|
||||
.message = bun.String.static("uv_interface_addresses failed"),
|
||||
.code = bun.String.static("ERR_SYSTEM_ERROR"),
|
||||
//.info = info,
|
||||
.errno = err,
|
||||
.errno = @intCast(-err),
|
||||
.syscall = bun.String.static("uv_interface_addresses"),
|
||||
};
|
||||
return globalThis.throwValue(sys_err.toErrorInstance(globalThis));
|
||||
});
|
||||
}
|
||||
defer libuv.uv_free_interface_addresses(ifaces, count);
|
||||
|
||||
@@ -825,8 +821,8 @@ pub fn setPriority1(global: *JSC.JSGlobalObject, pid: i32, priority: i32) !void
|
||||
.message = bun.String.static("no such process"),
|
||||
.code = bun.String.static("ESRCH"),
|
||||
.errno = comptime switch (bun.Environment.os) {
|
||||
else => -@as(c_int, @intFromEnum(std.posix.E.SRCH)),
|
||||
.windows => libuv.UV_ESRCH,
|
||||
else => @intFromEnum(std.posix.E.SRCH),
|
||||
.windows => -libuv.UV_ESRCH,
|
||||
},
|
||||
.syscall = bun.String.static("uv_os_getpriority"),
|
||||
};
|
||||
@@ -837,8 +833,8 @@ pub fn setPriority1(global: *JSC.JSGlobalObject, pid: i32, priority: i32) !void
|
||||
.message = bun.String.static("permission denied"),
|
||||
.code = bun.String.static("EACCES"),
|
||||
.errno = comptime switch (bun.Environment.os) {
|
||||
else => -@as(c_int, @intFromEnum(std.posix.E.ACCES)),
|
||||
.windows => libuv.UV_EACCES,
|
||||
else => @intFromEnum(std.posix.E.ACCES),
|
||||
.windows => -libuv.UV_EACCES,
|
||||
},
|
||||
.syscall = bun.String.static("uv_os_getpriority"),
|
||||
};
|
||||
@@ -849,8 +845,8 @@ pub fn setPriority1(global: *JSC.JSGlobalObject, pid: i32, priority: i32) !void
|
||||
.message = bun.String.static("operation not permitted"),
|
||||
.code = bun.String.static("EPERM"),
|
||||
.errno = comptime switch (bun.Environment.os) {
|
||||
else => -@as(c_int, @intFromEnum(std.posix.E.SRCH)),
|
||||
.windows => libuv.UV_ESRCH,
|
||||
else => @intFromEnum(std.posix.E.SRCH),
|
||||
.windows => -libuv.UV_ESRCH,
|
||||
},
|
||||
.syscall = bun.String.static("uv_os_getpriority"),
|
||||
};
|
||||
@@ -897,19 +893,11 @@ pub fn totalmem() u64 {
|
||||
}
|
||||
|
||||
pub fn uptime(global: *JSC.JSGlobalObject) bun.JSError!f64 {
|
||||
_ = global;
|
||||
switch (Environment.os) {
|
||||
.windows => {
|
||||
var uptime_value: f64 = undefined;
|
||||
const err = libuv.uv_uptime(&uptime_value);
|
||||
if (err != 0) {
|
||||
const sys_err = JSC.SystemError{
|
||||
.message = bun.String.static("failed to get system uptime"),
|
||||
.code = bun.String.static("ERR_SYSTEM_ERROR"),
|
||||
.errno = err,
|
||||
.syscall = bun.String.static("uv_uptime"),
|
||||
};
|
||||
return global.throwValue(sys_err.toErrorInstance(global));
|
||||
}
|
||||
_ = libuv.uv_uptime(&uptime_value);
|
||||
return uptime_value;
|
||||
},
|
||||
.mac => {
|
||||
|
||||
@@ -298,11 +298,10 @@ pub fn JSSink(comptime SinkType: type, comptime abi_name: []const u8) type {
|
||||
const Static = struct {
|
||||
pub const message = std.fmt.comptimePrint("{s} is not constructable", .{SinkType.name});
|
||||
};
|
||||
const err = JSC.SystemError{
|
||||
return JSC.SystemError.throw(globalThis, .{
|
||||
.message = bun.String.static(Static.message),
|
||||
.code = bun.String.static(@tagName(.ERR_ILLEGAL_CONSTRUCTOR)),
|
||||
};
|
||||
return globalThis.throwValue(err.toErrorInstance(globalThis));
|
||||
});
|
||||
}
|
||||
|
||||
var this = bun.new(SinkType, undefined);
|
||||
|
||||
@@ -1695,7 +1695,7 @@ pub const Error = enum(i32) {
|
||||
|
||||
pub fn reject(this: *Deferred, globalThis: *JSC.JSGlobalObject) void {
|
||||
const system_error = JSC.SystemError{
|
||||
.errno = @intFromEnum(this.errno),
|
||||
.errno = @intCast(@intFromEnum(this.errno)),
|
||||
.code = bun.String.static(this.errno.code()),
|
||||
.message = if (this.hostname) |hostname| bun.String.createFormat("{s} {s} {s}", .{ this.syscall, this.errno.code()[4..], hostname }) catch bun.outOfMemory() else bun.String.empty,
|
||||
.syscall = bun.String.createUTF8(this.syscall),
|
||||
@@ -1747,7 +1747,7 @@ pub const Error = enum(i32) {
|
||||
|
||||
pub fn toJS(this: Error, globalThis: *JSC.JSGlobalObject) JSC.JSValue {
|
||||
const instance = (JSC.SystemError{
|
||||
.errno = @intFromEnum(this),
|
||||
.errno = @intCast(@intFromEnum(this)),
|
||||
.code = bun.String.static(this.code()),
|
||||
}).toErrorInstance(globalThis);
|
||||
instance.put(globalThis, "name", bun.String.static("DNSException").toJS(globalThis));
|
||||
@@ -1756,7 +1756,7 @@ pub const Error = enum(i32) {
|
||||
|
||||
pub fn toJSWithSyscall(this: Error, globalThis: *JSC.JSGlobalObject, comptime syscall: []const u8) JSC.JSValue {
|
||||
const instance = (JSC.SystemError{
|
||||
.errno = @intFromEnum(this),
|
||||
.errno = @intCast(@intFromEnum(this)),
|
||||
.code = bun.String.static(this.code()),
|
||||
.syscall = bun.String.static((syscall ++ "\x00")[0..syscall.len :0]),
|
||||
}).toErrorInstance(globalThis);
|
||||
@@ -1766,7 +1766,7 @@ pub const Error = enum(i32) {
|
||||
|
||||
pub fn toJSWithSyscallAndHostname(this: Error, globalThis: *JSC.JSGlobalObject, comptime syscall: []const u8, hostname: []const u8) JSC.JSValue {
|
||||
const instance = (JSC.SystemError{
|
||||
.errno = @intFromEnum(this),
|
||||
.errno = @intCast(@intFromEnum(this)),
|
||||
.code = bun.String.static(this.code()),
|
||||
.message = bun.String.createFormat("{s} {s} {s}", .{ syscall, this.code()[4..], hostname }) catch bun.outOfMemory(),
|
||||
.syscall = bun.String.static((syscall ++ "\x00")[0..syscall.len :0]),
|
||||
|
||||
@@ -196,12 +196,12 @@ pub const SocketContext = opaque {
|
||||
return c.us_socket_context_adopt_socket(@intFromBool(ssl), this, s, ext_size);
|
||||
}
|
||||
|
||||
pub fn connect(this: *SocketContext, ssl: bool, host: [*:0]const u8, port: i32, options: i32, socket_ext_size: i32, has_dns_resolved: *i32) ?*anyopaque {
|
||||
return c.us_socket_context_connect(@intFromBool(ssl), this, host, port, options, socket_ext_size, has_dns_resolved);
|
||||
pub fn connect(this: *SocketContext, ssl: bool, host: [*:0]const u8, port: i32, options: i32, socket_ext_size: i32, has_dns_resolved: *i32, error_: ?*i32) ?*anyopaque {
|
||||
return c.us_socket_context_connect(@intFromBool(ssl), this, host, port, options, socket_ext_size, has_dns_resolved, error_);
|
||||
}
|
||||
|
||||
pub fn connectUnix(this: *SocketContext, ssl: bool, path: [:0]const u8, options: i32, socket_ext_size: i32) ?*us_socket_t {
|
||||
return c.us_socket_context_connect_unix(@intFromBool(ssl), this, path.ptr, path.len, options, socket_ext_size);
|
||||
pub fn connectUnix(this: *SocketContext, ssl: bool, path: [:0]const u8, options: i32, socket_ext_size: i32, error_: ?*i32) ?*us_socket_t {
|
||||
return c.us_socket_context_connect_unix(@intFromBool(ssl), this, path.ptr, path.len, options, socket_ext_size, error_);
|
||||
}
|
||||
|
||||
pub fn free(this: *SocketContext, ssl: bool) void {
|
||||
@@ -254,8 +254,8 @@ pub const c = struct {
|
||||
pub extern fn us_create_child_socket_context(ssl: i32, context: ?*SocketContext, context_ext_size: i32) ?*SocketContext;
|
||||
pub extern fn us_socket_context_adopt_socket(ssl: i32, context: *SocketContext, s: *us_socket_t, ext_size: i32) ?*us_socket_t;
|
||||
pub extern fn us_socket_context_close(ssl: i32, ctx: *anyopaque) void;
|
||||
pub extern fn us_socket_context_connect(ssl: i32, context: *SocketContext, host: [*:0]const u8, port: i32, options: i32, socket_ext_size: i32, has_dns_resolved: *i32) ?*anyopaque;
|
||||
pub extern fn us_socket_context_connect_unix(ssl: i32, context: *SocketContext, path: [*:0]const u8, pathlen: usize, options: i32, socket_ext_size: i32) ?*us_socket_t;
|
||||
pub extern fn us_socket_context_connect(ssl: i32, context: *SocketContext, host: [*:0]const u8, port: i32, options: i32, socket_ext_size: i32, has_dns_resolved: *i32, error_: ?*i32) ?*anyopaque;
|
||||
pub extern fn us_socket_context_connect_unix(ssl: i32, context: *SocketContext, path: [*:0]const u8, pathlen: usize, options: i32, socket_ext_size: i32, error_: ?*i32) ?*us_socket_t;
|
||||
pub extern fn us_socket_context_ext(ssl: i32, context: *SocketContext) ?*anyopaque;
|
||||
pub extern fn us_socket_context_free(ssl: i32, context: *SocketContext) void;
|
||||
pub extern fn us_socket_context_get_native_handle(ssl: i32, context: *SocketContext) ?*anyopaque;
|
||||
|
||||
@@ -326,6 +326,15 @@ pub fn NewSocketHandler(comptime is_ssl: bool) type {
|
||||
};
|
||||
}
|
||||
|
||||
pub fn writeMaybe(this: ThisSocket, data: []const u8, msg_more: bool) bun.Maybe(i32, bun.sys.Error) {
|
||||
return switch (this.socket) {
|
||||
.upgradedDuplex => |socket| .initResult(socket.encodeAndWrite(data, msg_more)),
|
||||
.pipe => |pipe| .initResult(if (comptime Environment.isWindows) pipe.encodeAndWrite(data, msg_more) else 0),
|
||||
.connected => |socket| socket.writeMaybe(is_ssl, data, msg_more),
|
||||
.connecting, .detached => .initResult(0),
|
||||
};
|
||||
}
|
||||
|
||||
pub fn writeFd(this: ThisSocket, data: []const u8, file_descriptor: bun.FileDescriptor) i32 {
|
||||
return switch (this.socket) {
|
||||
.upgradedDuplex, .pipe => this.write(data, false),
|
||||
@@ -506,8 +515,9 @@ pub fn NewSocketHandler(comptime is_ssl: bool) type {
|
||||
ctx: *Context,
|
||||
comptime socket_field_name: []const u8,
|
||||
allowHalfOpen: bool,
|
||||
error_: ?*i32,
|
||||
) !*Context {
|
||||
const this_socket = try connectAnon(host, port, socket_ctx, ctx, allowHalfOpen);
|
||||
const this_socket = try connectAnon(host, port, socket_ctx, ctx, allowHalfOpen, error_);
|
||||
@field(ctx, socket_field_name) = this_socket;
|
||||
return ctx;
|
||||
}
|
||||
@@ -574,6 +584,7 @@ pub fn NewSocketHandler(comptime is_ssl: bool) type {
|
||||
socket_ctx: *SocketContext,
|
||||
ctx: *anyopaque,
|
||||
allowHalfOpen: bool,
|
||||
error_: ?*i32,
|
||||
) !ThisSocket {
|
||||
debug("connect(unix:{s})", .{path});
|
||||
var stack_fallback = std.heap.stackFallback(1024, bun.default_allocator);
|
||||
@@ -581,7 +592,7 @@ pub fn NewSocketHandler(comptime is_ssl: bool) type {
|
||||
const path_ = allocator.dupeZ(u8, path) catch bun.outOfMemory();
|
||||
defer allocator.free(path_);
|
||||
|
||||
const socket = socket_ctx.connectUnix(is_ssl, path_, if (allowHalfOpen) uws.LIBUS_SOCKET_ALLOW_HALF_OPEN else 0, 8) orelse
|
||||
const socket = socket_ctx.connectUnix(is_ssl, path_, if (allowHalfOpen) uws.LIBUS_SOCKET_ALLOW_HALF_OPEN else 0, 8, error_) orelse
|
||||
return error.FailedToOpenSocket;
|
||||
|
||||
const socket_ = ThisSocket{ .socket = .{ .connected = socket } };
|
||||
@@ -597,6 +608,7 @@ pub fn NewSocketHandler(comptime is_ssl: bool) type {
|
||||
socket_ctx: *SocketContext,
|
||||
ptr: *anyopaque,
|
||||
allowHalfOpen: bool,
|
||||
error_: ?*i32,
|
||||
) !ThisSocket {
|
||||
debug("connect({s}, {d})", .{ raw_host, port });
|
||||
var stack_fallback = std.heap.stackFallback(1024, bun.default_allocator);
|
||||
@@ -619,6 +631,7 @@ pub fn NewSocketHandler(comptime is_ssl: bool) type {
|
||||
if (allowHalfOpen) uws.LIBUS_SOCKET_ALLOW_HALF_OPEN else 0,
|
||||
@sizeOf(*anyopaque),
|
||||
&did_dns_resolve,
|
||||
error_,
|
||||
) orelse return error.FailedToOpenSocket;
|
||||
const socket = if (did_dns_resolve == 1)
|
||||
ThisSocket{
|
||||
|
||||
@@ -133,11 +133,19 @@ pub const us_socket_t = opaque {
|
||||
}
|
||||
|
||||
pub fn write(this: *us_socket_t, ssl: bool, data: []const u8, msg_more: bool) i32 {
|
||||
const rc = c.us_socket_write(@intFromBool(ssl), this, data.ptr, @intCast(data.len), @intFromBool(msg_more));
|
||||
const rc = c.us_socket_write(@intFromBool(ssl), this, data.ptr, @intCast(data.len), @intFromBool(msg_more), null);
|
||||
debug("us_socket_write({d}, {d}) = {d}", .{ @intFromPtr(this), data.len, rc });
|
||||
return rc;
|
||||
}
|
||||
|
||||
pub fn writeMaybe(this: *us_socket_t, ssl: bool, data: []const u8, msg_more: bool) bun.Maybe(i32, bun.sys.Error) {
|
||||
var error_: i32 = 0;
|
||||
const rc = c.us_socket_write(@intFromBool(ssl), this, data.ptr, @intCast(data.len), @intFromBool(msg_more), &error_);
|
||||
debug("us_socket_write({d}, {d}) = {d}", .{ @intFromPtr(this), data.len, rc });
|
||||
if (error_ > 0) return .initErr(.fromCodeInt(error_, .write));
|
||||
return .initResult(rc);
|
||||
}
|
||||
|
||||
pub fn writeFd(this: *us_socket_t, data: []const u8, file_descriptor: bun.FD) i32 {
|
||||
if (bun.Environment.isWindows) @compileError("TODO: implement writeFd on Windows");
|
||||
const rc = c.us_socket_ipc_write_fd(this, data.ptr, @intCast(data.len), file_descriptor.native());
|
||||
@@ -145,8 +153,8 @@ pub const us_socket_t = opaque {
|
||||
return rc;
|
||||
}
|
||||
|
||||
pub fn write2(this: *us_socket_t, ssl: bool, first: []const u8, second: []const u8) i32 {
|
||||
const rc = c.us_socket_write2(@intFromBool(ssl), this, first.ptr, first.len, second.ptr, second.len);
|
||||
pub fn write2(this: *us_socket_t, ssl: bool, first: []const u8, second: []const u8, error_: ?*i32) i32 {
|
||||
const rc = c.us_socket_write2(@intFromBool(ssl), this, first.ptr, first.len, second.ptr, second.len, error_);
|
||||
debug("us_socket_write2({d}, {d}, {d}) = {d}", .{ @intFromPtr(this), first.len, second.len, rc });
|
||||
return rc;
|
||||
}
|
||||
@@ -204,9 +212,9 @@ pub const c = struct {
|
||||
pub extern fn us_socket_ext(ssl: i32, s: ?*us_socket_t) ?*anyopaque; // nullish to be safe
|
||||
pub extern fn us_socket_context(ssl: i32, s: ?*us_socket_t) ?*SocketContext;
|
||||
|
||||
pub extern fn us_socket_write(ssl: i32, s: ?*us_socket_t, data: [*c]const u8, length: i32, msg_more: i32) i32;
|
||||
pub extern fn us_socket_write(ssl: i32, s: ?*us_socket_t, data: [*c]const u8, length: i32, msg_more: i32, error_: ?*i32) i32;
|
||||
pub extern fn us_socket_ipc_write_fd(s: ?*us_socket_t, data: [*c]const u8, length: i32, fd: i32) i32;
|
||||
pub extern fn us_socket_write2(ssl: i32, *us_socket_t, header: ?[*]const u8, len: usize, payload: ?[*]const u8, usize) i32;
|
||||
pub extern fn us_socket_write2(ssl: i32, *us_socket_t, header: ?[*]const u8, len: usize, payload: ?[*]const u8, usize, error_: ?*i32) i32;
|
||||
pub extern fn us_socket_raw_write(ssl: i32, s: ?*us_socket_t, data: [*c]const u8, length: i32, msg_more: i32) i32;
|
||||
pub extern fn us_socket_flush(ssl: i32, s: ?*us_socket_t) void;
|
||||
|
||||
@@ -224,12 +232,7 @@ pub const c = struct {
|
||||
pub extern fn us_socket_get_fd(s: ?*us_socket_t) uws.LIBUS_SOCKET_DESCRIPTOR;
|
||||
pub extern fn us_socket_verify_error(ssl: i32, context: *us_socket_t) uws.us_bun_verify_error_t;
|
||||
pub extern fn us_socket_upgrade_to_tls(s: *us_socket_t, new_context: *SocketContext, sni: ?[*:0]const u8) ?*us_socket_t;
|
||||
pub extern fn us_socket_from_fd(
|
||||
ctx: *SocketContext,
|
||||
ext_size: c_int,
|
||||
fd: uws.LIBUS_SOCKET_DESCRIPTOR,
|
||||
is_ipc: c_int,
|
||||
) ?*us_socket_t;
|
||||
pub extern fn us_socket_from_fd(ctx: *SocketContext, ext_size: c_int, fd: uws.LIBUS_SOCKET_DESCRIPTOR, is_ipc: c_int) ?*us_socket_t;
|
||||
pub extern fn us_socket_get_error(ssl: i32, s: *uws.us_socket_t) c_int;
|
||||
pub extern fn us_socket_is_established(ssl: i32, s: *uws.us_socket_t) i32;
|
||||
};
|
||||
|
||||
@@ -123,6 +123,10 @@ pub const SystemErrno = enum(u16) {
|
||||
if (code >= max) return null;
|
||||
return @enumFromInt(code);
|
||||
}
|
||||
|
||||
pub fn to_uv_errno(this: SystemErrno) c_int {
|
||||
return @intFromEnum(this);
|
||||
}
|
||||
};
|
||||
pub const UV_E = struct {
|
||||
pub const @"2BIG": i32 = @intFromEnum(SystemErrno.E2BIG);
|
||||
|
||||
@@ -152,6 +152,10 @@ pub const SystemErrno = enum(u16) {
|
||||
if (code >= max) return null;
|
||||
return @enumFromInt(code);
|
||||
}
|
||||
|
||||
pub fn to_uv_errno(this: SystemErrno) c_int {
|
||||
return @intFromEnum(this);
|
||||
}
|
||||
};
|
||||
pub const UV_E = struct {
|
||||
pub const @"2BIG": i32 = @intFromEnum(SystemErrno.E2BIG);
|
||||
|
||||
@@ -1091,6 +1091,234 @@ pub const SystemErrno = enum(u16) {
|
||||
|
||||
return @as(SystemErrno, @enumFromInt(code));
|
||||
}
|
||||
|
||||
pub fn to_uv_errno(this: SystemErrno) c_int {
|
||||
return @intFromEnum(@as(SystemErrno, switch (this) {
|
||||
.SUCCESS => .SUCCESS,
|
||||
.EPERM => .UV_EPERM,
|
||||
.ENOENT => .UV_ENOENT,
|
||||
.ESRCH => .UV_ESRCH,
|
||||
.EINTR => .UV_EINTR,
|
||||
.EIO => .UV_EIO,
|
||||
.ENXIO => .UV_ENXIO,
|
||||
.E2BIG => .UV_E2BIG,
|
||||
.ENOEXEC => unreachable,
|
||||
.EBADF => .UV_EBADF,
|
||||
.ECHILD => unreachable,
|
||||
.EAGAIN => .UV_EAGAIN,
|
||||
.ENOMEM => .UV_ENOMEM,
|
||||
.EACCES => .UV_EACCES,
|
||||
.EFAULT => .UV_EFAULT,
|
||||
.ENOTBLK => unreachable,
|
||||
.EBUSY => .UV_EBUSY,
|
||||
.EEXIST => .UV_EEXIST,
|
||||
.EXDEV => .UV_EXDEV,
|
||||
.ENODEV => .UV_ENODEV,
|
||||
.ENOTDIR => .UV_ENOTDIR,
|
||||
.EISDIR => .UV_EISDIR,
|
||||
.EINVAL => .UV_EINVAL,
|
||||
.ENFILE => .UV_ENFILE,
|
||||
.EMFILE => .UV_EMFILE,
|
||||
.ENOTTY => .UV_ENOTTY,
|
||||
.ETXTBSY => .UV_ETXTBSY,
|
||||
.EFBIG => .UV_EFBIG,
|
||||
.ENOSPC => .UV_ENOSPC,
|
||||
.ESPIPE => .UV_ESPIPE,
|
||||
.EROFS => .UV_EROFS,
|
||||
.EMLINK => .UV_EMLINK,
|
||||
.EPIPE => .UV_EPIPE,
|
||||
.EDOM => unreachable,
|
||||
.ERANGE => .UV_ERANGE,
|
||||
.EDEADLK => unreachable,
|
||||
.ENAMETOOLONG => .UV_ENAMETOOLONG,
|
||||
.ENOLCK => unreachable,
|
||||
.ENOSYS => .UV_ENOSYS,
|
||||
.ENOTEMPTY => .UV_ENOTEMPTY,
|
||||
.ELOOP => .UV_ELOOP,
|
||||
.EWOULDBLOCK => unreachable,
|
||||
.ENOMSG => unreachable,
|
||||
.EIDRM => unreachable,
|
||||
.ECHRNG => unreachable,
|
||||
.EL2NSYNC => unreachable,
|
||||
.EL3HLT => unreachable,
|
||||
.EL3RST => unreachable,
|
||||
.ELNRNG => unreachable,
|
||||
.EUNATCH => .UV_EUNATCH,
|
||||
.ENOCSI => unreachable,
|
||||
.EL2HLT => unreachable,
|
||||
.EBADE => unreachable,
|
||||
.EBADR => unreachable,
|
||||
.EXFULL => unreachable,
|
||||
.ENOANO => unreachable,
|
||||
.EBADRQC => unreachable,
|
||||
.EBADSLT => unreachable,
|
||||
.EDEADLOCK => unreachable,
|
||||
.EBFONT => unreachable,
|
||||
.ENOSTR => unreachable,
|
||||
.ENODATA => .UV_ENODATA,
|
||||
.ETIME => unreachable,
|
||||
.ENOSR => unreachable,
|
||||
.ENONET => .UV_ENONET,
|
||||
.ENOPKG => unreachable,
|
||||
.EREMOTE => unreachable,
|
||||
.ENOLINK => unreachable,
|
||||
.EADV => unreachable,
|
||||
.ESRMNT => unreachable,
|
||||
.ECOMM => unreachable,
|
||||
.EPROTO => .UV_EPROTO,
|
||||
.EMULTIHOP => unreachable,
|
||||
.EDOTDOT => unreachable,
|
||||
.EBADMSG => unreachable,
|
||||
.EOVERFLOW => .UV_EOVERFLOW,
|
||||
.ENOTUNIQ => unreachable,
|
||||
.EBADFD => unreachable,
|
||||
.EREMCHG => unreachable,
|
||||
.ELIBACC => unreachable,
|
||||
.ELIBBAD => unreachable,
|
||||
.ELIBSCN => unreachable,
|
||||
.ELIBMAX => unreachable,
|
||||
.ELIBEXEC => unreachable,
|
||||
.EILSEQ => .UV_EILSEQ,
|
||||
.ERESTART => unreachable,
|
||||
.ESTRPIPE => unreachable,
|
||||
.EUSERS => unreachable,
|
||||
.ENOTSOCK => .UV_ENOTSOCK,
|
||||
.EDESTADDRREQ => .UV_EDESTADDRREQ,
|
||||
.EMSGSIZE => .UV_EMSGSIZE,
|
||||
.EPROTOTYPE => .UV_EPROTOTYPE,
|
||||
.ENOPROTOOPT => .UV_ENOPROTOOPT,
|
||||
.EPROTONOSUPPORT => .UV_EPROTONOSUPPORT,
|
||||
.ESOCKTNOSUPPORT => .UV_ESOCKTNOSUPPORT,
|
||||
.ENOTSUP => .UV_ENOTSUP,
|
||||
.EPFNOSUPPORT => unreachable,
|
||||
.EAFNOSUPPORT => .UV_EAFNOSUPPORT,
|
||||
.EADDRINUSE => .UV_EADDRINUSE,
|
||||
.EADDRNOTAVAIL => .UV_EADDRNOTAVAIL,
|
||||
.ENETDOWN => .UV_ENETDOWN,
|
||||
.ENETUNREACH => .UV_ENETUNREACH,
|
||||
.ENETRESET => unreachable,
|
||||
.ECONNABORTED => .UV_ECONNABORTED,
|
||||
.ECONNRESET => .UV_ECONNRESET,
|
||||
.ENOBUFS => .UV_ENOBUFS,
|
||||
.EISCONN => .UV_EISCONN,
|
||||
.ENOTCONN => .UV_ENOTCONN,
|
||||
.ESHUTDOWN => .UV_ESHUTDOWN,
|
||||
.ETOOMANYREFS => unreachable,
|
||||
.ETIMEDOUT => .UV_ETIMEDOUT,
|
||||
.ECONNREFUSED => .UV_ECONNREFUSED,
|
||||
.EHOSTDOWN => .UV_EHOSTDOWN,
|
||||
.EHOSTUNREACH => .UV_EHOSTUNREACH,
|
||||
.EALREADY => .UV_EALREADY,
|
||||
.EINPROGRESS => unreachable,
|
||||
.ESTALE => unreachable,
|
||||
.EUCLEAN => unreachable,
|
||||
.ENOTNAM => unreachable,
|
||||
.ENAVAIL => unreachable,
|
||||
.EISNAM => unreachable,
|
||||
.EREMOTEIO => .UV_EREMOTEIO,
|
||||
.EDQUOT => unreachable,
|
||||
.ENOMEDIUM => unreachable,
|
||||
.EMEDIUMTYPE => unreachable,
|
||||
.ECANCELED => .UV_ECANCELED,
|
||||
.ENOKEY => unreachable,
|
||||
.EKEYEXPIRED => unreachable,
|
||||
.EKEYREVOKED => unreachable,
|
||||
.EKEYREJECTED => unreachable,
|
||||
.EOWNERDEAD => unreachable,
|
||||
.ENOTRECOVERABLE => unreachable,
|
||||
.ERFKILL => unreachable,
|
||||
.EHWPOISON => unreachable,
|
||||
.EUNKNOWN => unreachable,
|
||||
.ECHARSET => .UV_ECHARSET,
|
||||
.EOF => .UV_EOF,
|
||||
|
||||
.UV_E2BIG => .UV_E2BIG,
|
||||
.UV_EACCES => .UV_EACCES,
|
||||
.UV_EADDRINUSE => .UV_EADDRINUSE,
|
||||
.UV_EADDRNOTAVAIL => .UV_EADDRNOTAVAIL,
|
||||
.UV_EAFNOSUPPORT => .UV_EAFNOSUPPORT,
|
||||
.UV_EAGAIN => .UV_EAGAIN,
|
||||
.UV_EAI_ADDRFAMILY => .UV_EAI_ADDRFAMILY,
|
||||
.UV_EAI_AGAIN => .UV_EAI_AGAIN,
|
||||
.UV_EAI_BADFLAGS => .UV_EAI_BADFLAGS,
|
||||
.UV_EAI_BADHINTS => .UV_EAI_BADHINTS,
|
||||
.UV_EAI_CANCELED => .UV_EAI_CANCELED,
|
||||
.UV_EAI_FAIL => .UV_EAI_FAIL,
|
||||
.UV_EAI_FAMILY => .UV_EAI_FAMILY,
|
||||
.UV_EAI_MEMORY => .UV_EAI_MEMORY,
|
||||
.UV_EAI_NODATA => .UV_EAI_NODATA,
|
||||
.UV_EAI_NONAME => .UV_EAI_NONAME,
|
||||
.UV_EAI_OVERFLOW => .UV_EAI_OVERFLOW,
|
||||
.UV_EAI_PROTOCOL => .UV_EAI_PROTOCOL,
|
||||
.UV_EAI_SERVICE => .UV_EAI_SERVICE,
|
||||
.UV_EAI_SOCKTYPE => .UV_EAI_SOCKTYPE,
|
||||
.UV_EALREADY => .UV_EALREADY,
|
||||
.UV_EBADF => .UV_EBADF,
|
||||
.UV_EBUSY => .UV_EBUSY,
|
||||
.UV_ECANCELED => .UV_ECANCELED,
|
||||
.UV_ECHARSET => .UV_ECHARSET,
|
||||
.UV_ECONNABORTED => .UV_ECONNABORTED,
|
||||
.UV_ECONNREFUSED => .UV_ECONNREFUSED,
|
||||
.UV_ECONNRESET => .UV_ECONNRESET,
|
||||
.UV_EDESTADDRREQ => .UV_EDESTADDRREQ,
|
||||
.UV_EEXIST => .UV_EEXIST,
|
||||
.UV_EFAULT => .UV_EFAULT,
|
||||
.UV_EFBIG => .UV_EFBIG,
|
||||
.UV_EHOSTUNREACH => .UV_EHOSTUNREACH,
|
||||
.UV_EINVAL => .UV_EINVAL,
|
||||
.UV_EINTR => .UV_EINTR,
|
||||
.UV_EISCONN => .UV_EISCONN,
|
||||
.UV_EIO => .UV_EIO,
|
||||
.UV_ELOOP => .UV_ELOOP,
|
||||
.UV_EISDIR => .UV_EISDIR,
|
||||
.UV_EMSGSIZE => .UV_EMSGSIZE,
|
||||
.UV_EMFILE => .UV_EMFILE,
|
||||
.UV_ENETDOWN => .UV_ENETDOWN,
|
||||
.UV_ENAMETOOLONG => .UV_ENAMETOOLONG,
|
||||
.UV_ENFILE => .UV_ENFILE,
|
||||
.UV_ENETUNREACH => .UV_ENETUNREACH,
|
||||
.UV_ENODEV => .UV_ENODEV,
|
||||
.UV_ENOBUFS => .UV_ENOBUFS,
|
||||
.UV_ENOMEM => .UV_ENOMEM,
|
||||
.UV_ENOENT => .UV_ENOENT,
|
||||
.UV_ENOPROTOOPT => .UV_ENOPROTOOPT,
|
||||
.UV_ENONET => .UV_ENONET,
|
||||
.UV_ENOSYS => .UV_ENOSYS,
|
||||
.UV_ENOSPC => .UV_ENOSPC,
|
||||
.UV_ENOTDIR => .UV_ENOTDIR,
|
||||
.UV_ENOTCONN => .UV_ENOTCONN,
|
||||
.UV_ENOTSOCK => .UV_ENOTSOCK,
|
||||
.UV_ENOTEMPTY => .UV_ENOTEMPTY,
|
||||
.UV_EOVERFLOW => .UV_EOVERFLOW,
|
||||
.UV_ENOTSUP => .UV_ENOTSUP,
|
||||
.UV_EPIPE => .UV_EPIPE,
|
||||
.UV_EPERM => .UV_EPERM,
|
||||
.UV_EPROTONOSUPPORT => .UV_EPROTONOSUPPORT,
|
||||
.UV_EPROTO => .UV_EPROTO,
|
||||
.UV_ERANGE => .UV_ERANGE,
|
||||
.UV_EPROTOTYPE => .UV_EPROTOTYPE,
|
||||
.UV_ESHUTDOWN => .UV_ESHUTDOWN,
|
||||
.UV_EROFS => .UV_EROFS,
|
||||
.UV_ESRCH => .UV_ESRCH,
|
||||
.UV_ESPIPE => .UV_ESPIPE,
|
||||
.UV_ETXTBSY => .UV_ETXTBSY,
|
||||
.UV_ETIMEDOUT => .UV_ETIMEDOUT,
|
||||
.UV_UNKNOWN => .UV_UNKNOWN,
|
||||
.UV_EXDEV => .UV_EXDEV,
|
||||
.UV_ENXIO => .UV_ENXIO,
|
||||
.UV_EOF => .UV_EOF,
|
||||
.UV_EHOSTDOWN => .UV_EHOSTDOWN,
|
||||
.UV_EMLINK => .UV_EMLINK,
|
||||
.UV_ENOTTY => .UV_ENOTTY,
|
||||
.UV_EREMOTEIO => .UV_EREMOTEIO,
|
||||
.UV_EILSEQ => .UV_EILSEQ,
|
||||
.UV_EFTYPE => .UV_EFTYPE,
|
||||
.UV_ENODATA => .UV_ENODATA,
|
||||
.UV_ESOCKTNOSUPPORT => .UV_ESOCKTNOSUPPORT,
|
||||
.UV_ERRNO_MAX => .UV_ERRNO_MAX,
|
||||
.UV_EUNATCH => .UV_EUNATCH,
|
||||
}));
|
||||
}
|
||||
};
|
||||
|
||||
pub const UV_E = struct {
|
||||
@@ -1167,3 +1395,53 @@ const std = @import("std");
|
||||
const bun = @import("bun");
|
||||
const uv = bun.windows.libuv;
|
||||
const Win32Error = bun.windows.Win32Error;
|
||||
|
||||
export fn us_wsa_to_libuv_errno(code: c_int) c_int {
|
||||
return @intFromEnum(switch (@as(Win32Error, @enumFromInt(code))) {
|
||||
.SUCCESS => .SUCCESS,
|
||||
Win32Error.WSAEINTR => SystemErrno.UV_EINTR,
|
||||
Win32Error.WSAEBADF => SystemErrno.UV_EBADF,
|
||||
Win32Error.WSAEACCES => SystemErrno.UV_EACCES,
|
||||
Win32Error.WSAEFAULT => SystemErrno.UV_EFAULT,
|
||||
Win32Error.WSAEINVAL => SystemErrno.UV_EINVAL,
|
||||
Win32Error.WSAEMFILE => SystemErrno.UV_EMFILE,
|
||||
Win32Error.WSAEWOULDBLOCK => SystemErrno.UV_EAGAIN,
|
||||
Win32Error.WSAEINPROGRESS => SystemErrno.UV_EAGAIN,
|
||||
Win32Error.WSAEALREADY => SystemErrno.UV_EALREADY,
|
||||
Win32Error.WSAENOTSOCK => SystemErrno.UV_ENOTSOCK,
|
||||
Win32Error.WSAEDESTADDRREQ => SystemErrno.UV_EDESTADDRREQ,
|
||||
Win32Error.WSAEMSGSIZE => SystemErrno.UV_EMSGSIZE,
|
||||
Win32Error.WSAEPROTOTYPE => SystemErrno.UV_EPROTOTYPE,
|
||||
Win32Error.WSAENOPROTOOPT => SystemErrno.UV_ENOPROTOOPT,
|
||||
Win32Error.WSAEPROTONOSUPPORT => SystemErrno.UV_EPROTONOSUPPORT,
|
||||
Win32Error.WSAESOCKTNOSUPPORT => SystemErrno.UV_ESOCKTNOSUPPORT,
|
||||
Win32Error.WSAEOPNOTSUPP => SystemErrno.UV_ENOTSUP,
|
||||
Win32Error.WSAEPFNOSUPPORT => SystemErrno.UV_ENOTSUP,
|
||||
Win32Error.WSAEAFNOSUPPORT => SystemErrno.UV_EAFNOSUPPORT,
|
||||
Win32Error.WSAEADDRINUSE => SystemErrno.UV_EADDRINUSE,
|
||||
Win32Error.WSAEADDRNOTAVAIL => SystemErrno.UV_EADDRNOTAVAIL,
|
||||
Win32Error.WSAENETDOWN => SystemErrno.UV_ENETDOWN,
|
||||
Win32Error.WSAENETUNREACH => SystemErrno.UV_ENETUNREACH,
|
||||
// Win32Error.WSAENETRESET => SystemErrno.UV_ENETRESET,
|
||||
Win32Error.WSAECONNABORTED => SystemErrno.UV_ECONNABORTED,
|
||||
Win32Error.WSAECONNRESET => SystemErrno.UV_ECONNRESET,
|
||||
Win32Error.WSAENOBUFS => SystemErrno.UV_ENOBUFS,
|
||||
Win32Error.WSAEISCONN => SystemErrno.UV_EISCONN,
|
||||
Win32Error.WSAENOTCONN => SystemErrno.UV_ENOTCONN,
|
||||
Win32Error.WSAESHUTDOWN => SystemErrno.UV_ESHUTDOWN,
|
||||
// Win32Error.WSAETOOMANYREFS => SystemErrno.UV_ETOOMANYREFS,
|
||||
Win32Error.WSAETIMEDOUT => SystemErrno.UV_ETIMEDOUT,
|
||||
Win32Error.WSAECONNREFUSED => SystemErrno.UV_ECONNREFUSED,
|
||||
Win32Error.WSAELOOP => SystemErrno.UV_ELOOP,
|
||||
Win32Error.WSAENAMETOOLONG => SystemErrno.UV_ENAMETOOLONG,
|
||||
Win32Error.WSAEHOSTDOWN => SystemErrno.UV_EHOSTDOWN,
|
||||
Win32Error.WSAEHOSTUNREACH => SystemErrno.UV_EHOSTUNREACH,
|
||||
Win32Error.WSAENOTEMPTY => SystemErrno.UV_ENOTEMPTY,
|
||||
// Win32Error.WSAEPROCLIM => SystemErrno.UV_EPROCLIM,
|
||||
// Win32Error.WSAEUSERS => SystemErrno.UV_EUSERS,
|
||||
// Win32Error.WSAEDQUOT => SystemErrno.UV_EDQUOT,
|
||||
// Win32Error.WSAESTALE => SystemErrno.UV_ESTALE,
|
||||
// Win32Error.WSAEREMOTE => SystemErrno.UV_EREMOTE,
|
||||
else => bun.Output.panic("us_wsa_to_libuv_errno: unexpected code: {d}", .{code}),
|
||||
});
|
||||
}
|
||||
|
||||
@@ -1017,6 +1017,7 @@ fn NewHTTPContext(comptime ssl: bool) type {
|
||||
this.us_socket_context,
|
||||
ActiveSocket.init(client).ptr(),
|
||||
false, // dont allow half-open sockets
|
||||
null,
|
||||
);
|
||||
client.allow_retry = false;
|
||||
return socket;
|
||||
@@ -1051,6 +1052,7 @@ fn NewHTTPContext(comptime ssl: bool) type {
|
||||
this.us_socket_context,
|
||||
ActiveSocket.init(client).ptr(),
|
||||
false,
|
||||
null,
|
||||
);
|
||||
client.allow_retry = false;
|
||||
return socket;
|
||||
@@ -3316,10 +3318,7 @@ noinline fn sendInitialRequestPayload(this: *HTTPClient, comptime is_first_call:
|
||||
assert(!socket.isShutdown());
|
||||
assert(!socket.isClosed());
|
||||
}
|
||||
const amount = socket.write(
|
||||
to_send,
|
||||
false,
|
||||
);
|
||||
const amount = socket.write(to_send, false);
|
||||
if (comptime is_first_call) {
|
||||
if (amount == 0) {
|
||||
// don't worry about it
|
||||
|
||||
@@ -124,6 +124,7 @@ pub fn NewHTTPUpgradeClient(comptime ssl: bool) type {
|
||||
client,
|
||||
"tcp",
|
||||
false,
|
||||
null,
|
||||
)) |out| {
|
||||
// I don't think this case gets reached.
|
||||
if (out.state == .failed) {
|
||||
|
||||
@@ -31,7 +31,7 @@ import type { Socket, SocketHandler, SocketListener } from "bun";
|
||||
import type { Server as NetServer, Socket as NetSocket, ServerOpts } from "node:net";
|
||||
import type { TLSSocket } from "node:tls";
|
||||
const { kTimeout, getTimerDuration } = require("internal/timers");
|
||||
const { validateFunction, validateNumber, validateAbortSignal, validatePort, validateBoolean, validateInt32 } = require("internal/validators"); // prettier-ignore
|
||||
const { validateFunction, validateNumber, validateAbortSignal, validatePort, validateBoolean, validateInt32, validateString } = require("internal/validators"); // prettier-ignore
|
||||
const { NodeAggregateError, ErrnoException } = require("internal/shared");
|
||||
|
||||
const ArrayPrototypeIncludes = Array.prototype.includes;
|
||||
@@ -231,7 +231,7 @@ const SocketHandlers: SocketHandler = {
|
||||
callback(error);
|
||||
}
|
||||
|
||||
self.emit("error", error);
|
||||
if (!self.destroyed) process.nextTick(destroyNT, self, error);
|
||||
},
|
||||
open(socket) {
|
||||
const self = socket.data;
|
||||
@@ -360,7 +360,7 @@ const ServerHandlers: SocketHandler<NetSocket> = {
|
||||
const self = socket.data as any as NetServer;
|
||||
socket[kServerSocket] = self._handle;
|
||||
const options = self[bunSocketServerOptions];
|
||||
const { pauseOnConnect, connectionListener, [kSocketClass]: SClass, requestCert, rejectUnauthorized } = options;
|
||||
const { pauseOnConnect, [kSocketClass]: SClass, requestCert, rejectUnauthorized } = options;
|
||||
const _socket = new SClass({}) as NetSocket | TLSSocket;
|
||||
_socket.isServer = true;
|
||||
_socket._requestCert = requestCert;
|
||||
@@ -409,12 +409,6 @@ const ServerHandlers: SocketHandler<NetSocket> = {
|
||||
_socket.pause();
|
||||
}
|
||||
|
||||
if (typeof connectionListener === "function") {
|
||||
this.pauseOnConnect = pauseOnConnect;
|
||||
if (!isTLS) {
|
||||
connectionListener.$call(self, _socket);
|
||||
}
|
||||
}
|
||||
self.emit("connection", _socket);
|
||||
// the duplex implementation start paused, so we resume when pauseOnConnect is falsy
|
||||
if (!pauseOnConnect && !isTLS) {
|
||||
@@ -455,10 +449,6 @@ const ServerHandlers: SocketHandler<NetSocket> = {
|
||||
} else {
|
||||
self.authorized = true;
|
||||
}
|
||||
const connectionListener = server[bunSocketServerOptions]?.connectionListener;
|
||||
if (typeof connectionListener === "function") {
|
||||
connectionListener.$call(server, self);
|
||||
}
|
||||
server.emit("secureConnection", self);
|
||||
// after secureConnection event we emmit secure and secureConnect
|
||||
self.emit("secure", self);
|
||||
@@ -474,7 +464,6 @@ const ServerHandlers: SocketHandler<NetSocket> = {
|
||||
if (!data) return;
|
||||
|
||||
if (data._hadError) return;
|
||||
data._hadError = true;
|
||||
const bunTLS = this[bunTlsSymbol];
|
||||
|
||||
if (typeof bunTLS === "function") {
|
||||
@@ -498,7 +487,6 @@ const ServerHandlers: SocketHandler<NetSocket> = {
|
||||
}
|
||||
}
|
||||
SocketHandlers.error(socket, error, true);
|
||||
data.server.emit("clientError", error, data);
|
||||
},
|
||||
timeout(socket) {
|
||||
SocketHandlers.timeout(socket);
|
||||
@@ -625,8 +613,6 @@ const SocketHandlers2: SocketHandler<NonNullable<import("node:net").Socket["_han
|
||||
self[kwriteCallback] = null;
|
||||
callback(error);
|
||||
}
|
||||
self.emit("error", error);
|
||||
|
||||
if (!self.destroyed) process.nextTick(destroyNT, self, error);
|
||||
},
|
||||
timeout(socket) {
|
||||
@@ -681,14 +667,14 @@ function kConnectPipe(self, req, address) {
|
||||
function Socket(options?) {
|
||||
if (!(this instanceof Socket)) return new Socket(options);
|
||||
|
||||
const {
|
||||
let {
|
||||
socket,
|
||||
signal,
|
||||
allowHalfOpen = false,
|
||||
onread = null,
|
||||
noDelay = false,
|
||||
keepAlive = false,
|
||||
keepAliveInitialDelay = 0,
|
||||
keepAliveInitialDelay,
|
||||
...opts
|
||||
} = options || {};
|
||||
|
||||
@@ -698,6 +684,11 @@ function Socket(options?) {
|
||||
if (options?.writableObjectMode)
|
||||
throw $ERR_INVALID_ARG_VALUE("options.writableObjectMode", options.writableObjectMode, "is not supported");
|
||||
|
||||
if (keepAliveInitialDelay !== undefined) {
|
||||
validateNumber(keepAliveInitialDelay, "options.keepAliveInitialDelay");
|
||||
if (keepAliveInitialDelay < 0) keepAliveInitialDelay = 0;
|
||||
}
|
||||
|
||||
if (options?.fd !== undefined) {
|
||||
validateInt32(options.fd, "options.fd", 0);
|
||||
}
|
||||
@@ -1101,6 +1092,7 @@ Socket.prototype.connect = function connect(...args) {
|
||||
if (!pipe) {
|
||||
lookupAndConnect(this, options);
|
||||
} else {
|
||||
validateString(path, "options.path");
|
||||
internalConnect(this, options, path);
|
||||
}
|
||||
return this;
|
||||
@@ -1509,6 +1501,8 @@ function lookupAndConnect(self, options) {
|
||||
const host = options.host || "localhost";
|
||||
let { port, autoSelectFamilyAttemptTimeout, autoSelectFamily } = options;
|
||||
|
||||
validateString(host, "options.host");
|
||||
|
||||
if (localAddress && !isIP(localAddress)) {
|
||||
throw $ERR_INVALID_IP_ADDRESS(localAddress);
|
||||
}
|
||||
@@ -2059,10 +2053,10 @@ function createConnectionError(req, status) {
|
||||
|
||||
type MaybeListener = SocketListener<unknown> | null;
|
||||
|
||||
function Server();
|
||||
function Server(options?: null | undefined);
|
||||
function Server(connectionListener: () => {});
|
||||
function Server(options: ServerOpts, connectionListener?: () => {});
|
||||
function Server(): void;
|
||||
function Server(options?: null | undefined): void;
|
||||
function Server(connectionListener: () => {}): void;
|
||||
function Server(options: ServerOpts, connectionListener?: () => {}): void;
|
||||
function Server(options?, connectionListener?) {
|
||||
if (!(this instanceof Server)) {
|
||||
return new Server(options, connectionListener);
|
||||
@@ -2076,7 +2070,14 @@ function Server(options?, connectionListener?) {
|
||||
} else if (options == null || typeof options === "object") {
|
||||
options = { ...options };
|
||||
} else {
|
||||
throw $ERR_INVALID_ARG_TYPE("options", ["Object", "Function"], options);
|
||||
throw $ERR_INVALID_ARG_TYPE("options", "object", options);
|
||||
}
|
||||
if (typeof connectionListener === "function") {
|
||||
if (typeof this[bunTlsSymbol] === "function") {
|
||||
this.on("secureConnection", connectionListener);
|
||||
} else {
|
||||
this.on("connection", connectionListener);
|
||||
}
|
||||
}
|
||||
|
||||
// https://nodejs.org/api/net.html#netcreateserveroptions-connectionlistener
|
||||
@@ -2105,7 +2106,6 @@ function Server(options?, connectionListener?) {
|
||||
this.pauseOnConnect = Boolean(pauseOnConnect);
|
||||
this.noDelay = noDelay;
|
||||
|
||||
options.connectionListener = connectionListener;
|
||||
this[bunSocketServerOptions] = options;
|
||||
|
||||
if (options.blockList) {
|
||||
@@ -2437,6 +2437,16 @@ Server.prototype[kRealListen] = function (
|
||||
setTimeout(emitListeningNextTick, 1, this);
|
||||
};
|
||||
|
||||
Server.prototype[EventEmitter.captureRejectionSymbol] = function (err, event, sock) {
|
||||
switch (event) {
|
||||
case "connection":
|
||||
sock.destroy(err);
|
||||
break;
|
||||
default:
|
||||
this.emit("error", err);
|
||||
}
|
||||
};
|
||||
|
||||
Server.prototype.getsockname = function getsockname(out) {
|
||||
out.port = this.address().port;
|
||||
return out;
|
||||
|
||||
@@ -507,6 +507,7 @@ function Server(options, secureConnectionListener): void {
|
||||
return new Server(options, secureConnectionListener);
|
||||
}
|
||||
|
||||
this[buntls] = () => {}; // for detection, overwrote below
|
||||
NetServer.$apply(this, [options, secureConnectionListener]);
|
||||
|
||||
this.key = undefined;
|
||||
@@ -641,6 +642,7 @@ $toClass(Server, "Server", NetServer);
|
||||
function createServer(options, connectionListener) {
|
||||
return new Server(options, connectionListener);
|
||||
}
|
||||
|
||||
const DEFAULT_ECDH_CURVE = "auto",
|
||||
// https://github.com/Jarred-Sumner/uSockets/blob/fafc241e8664243fc0c51d69684d5d02b9805134/src/crypto/openssl.c#L519-L523
|
||||
DEFAULT_MIN_VERSION = "TLSv1.2",
|
||||
|
||||
@@ -1959,7 +1959,7 @@ pub const PostgresSQLConnection = struct {
|
||||
|
||||
if (path.len > 0) {
|
||||
ptr.socket = .{
|
||||
.SocketTCP = uws.SocketTCP.connectUnixAnon(path, ctx, ptr, false) catch |err| {
|
||||
.SocketTCP = uws.SocketTCP.connectUnixAnon(path, ctx, ptr, false, null) catch |err| {
|
||||
tls_config.deinit();
|
||||
if (tls_ctx) |tls| {
|
||||
tls.deinit(true);
|
||||
@@ -1970,7 +1970,7 @@ pub const PostgresSQLConnection = struct {
|
||||
};
|
||||
} else {
|
||||
ptr.socket = .{
|
||||
.SocketTCP = uws.SocketTCP.connectAnon(hostname.slice(), port, ctx, ptr, false) catch |err| {
|
||||
.SocketTCP = uws.SocketTCP.connectAnon(hostname.slice(), port, ctx, ptr, false, null) catch |err| {
|
||||
tls_config.deinit();
|
||||
if (tls_ctx) |tls| {
|
||||
tls.deinit(true);
|
||||
|
||||
@@ -9,9 +9,9 @@
|
||||
// like `Error`, `Maybe`, `Tag`, and so on.
|
||||
const sys = @This(); // to avoid ambiguous references.
|
||||
const platform_defs = switch (Environment.os) {
|
||||
.windows => @import("errno/windows_errno.zig"),
|
||||
.linux => @import("errno/linux_errno.zig"),
|
||||
.mac => @import("errno/darwin_errno.zig"),
|
||||
.linux => @import("errno/linux_errno.zig"),
|
||||
.windows => @import("errno/windows_errno.zig"),
|
||||
.wasm => {},
|
||||
};
|
||||
pub const workaround_symbols = @import("workaround_missing_symbols.zig").current;
|
||||
@@ -523,7 +523,7 @@ pub const Error = struct {
|
||||
pub fn toShellSystemError(this: Error) SystemError {
|
||||
@setEvalBranchQuota(1_000_000);
|
||||
var err = SystemError{
|
||||
.errno = @as(c_int, this.errno) * -1,
|
||||
.errno = this.errno,
|
||||
.syscall = bun.String.static(@tagName(this.syscall)),
|
||||
};
|
||||
|
||||
@@ -558,7 +558,7 @@ pub const Error = struct {
|
||||
/// Use this whenever the error will be sent to JavaScript instead of the shell variant above.
|
||||
pub fn toSystemError(this: Error) SystemError {
|
||||
var err = SystemError{
|
||||
.errno = -%@as(c_int, this.errno),
|
||||
.errno = this.errno,
|
||||
.syscall = bun.String.static(@tagName(this.syscall)),
|
||||
};
|
||||
|
||||
|
||||
@@ -114,6 +114,7 @@ pub const Address = union(enum) {
|
||||
ctx,
|
||||
client,
|
||||
false,
|
||||
null,
|
||||
));
|
||||
},
|
||||
.host => |h| {
|
||||
@@ -123,6 +124,7 @@ pub const Address = union(enum) {
|
||||
ctx,
|
||||
client,
|
||||
false,
|
||||
null,
|
||||
));
|
||||
},
|
||||
}
|
||||
|
||||
@@ -9,7 +9,7 @@ it("should throw when a socket from a file descriptor has a bad file descriptor"
|
||||
const open = jest.fn();
|
||||
const close = jest.fn();
|
||||
const data = jest.fn();
|
||||
const connectError = jest.fn(() => {});
|
||||
const connectError = jest.fn();
|
||||
{
|
||||
expect(
|
||||
async () =>
|
||||
@@ -213,7 +213,7 @@ it("should reject on connection error, calling both connectError() and rejecting
|
||||
var data = {};
|
||||
connect({
|
||||
data,
|
||||
hostname: "localhost",
|
||||
hostname: "127.0.0.1",
|
||||
port: 55555,
|
||||
socket: {
|
||||
connectError(socket, error) {
|
||||
@@ -288,7 +288,7 @@ it("should handle connection error", done => {
|
||||
var data = {};
|
||||
connect({
|
||||
data,
|
||||
hostname: "localhost",
|
||||
hostname: "127.0.0.1",
|
||||
port: 55555,
|
||||
socket: {
|
||||
connectError(socket, error) {
|
||||
|
||||
47
test/js/node/test/parallel/test-net-allow-half-open.js
Normal file
47
test/js/node/test/parallel/test-net-allow-half-open.js
Normal file
@@ -0,0 +1,47 @@
|
||||
'use strict';
|
||||
|
||||
const common = require('../common');
|
||||
const assert = require('assert');
|
||||
const net = require('net');
|
||||
|
||||
{
|
||||
const server = net.createServer(common.mustCall((socket) => {
|
||||
socket.end(Buffer.alloc(1024));
|
||||
})).listen(0, common.mustCall(() => {
|
||||
const socket = net.connect(server.address().port);
|
||||
assert.strictEqual(socket.allowHalfOpen, false);
|
||||
socket.resume();
|
||||
socket.on('end', common.mustCall(() => {
|
||||
process.nextTick(() => {
|
||||
// Ensure socket is not destroyed straight away
|
||||
// without proper shutdown.
|
||||
assert(!socket.destroyed);
|
||||
server.close();
|
||||
});
|
||||
}));
|
||||
socket.on('finish', common.mustCall(() => {
|
||||
assert(!socket.destroyed);
|
||||
}));
|
||||
socket.on('close', common.mustCall());
|
||||
}));
|
||||
}
|
||||
|
||||
{
|
||||
const server = net.createServer(common.mustCall((socket) => {
|
||||
socket.end(Buffer.alloc(1024));
|
||||
})).listen(0, common.mustCall(() => {
|
||||
const socket = net.connect(server.address().port);
|
||||
assert.strictEqual(socket.allowHalfOpen, false);
|
||||
socket.resume();
|
||||
socket.on('end', common.mustCall(() => {
|
||||
assert(!socket.destroyed);
|
||||
}));
|
||||
socket.end('asd');
|
||||
socket.on('finish', common.mustCall(() => {
|
||||
assert(!socket.destroyed);
|
||||
}));
|
||||
socket.on('close', common.mustCall(() => {
|
||||
server.close();
|
||||
}));
|
||||
}));
|
||||
}
|
||||
@@ -0,0 +1,22 @@
|
||||
'use strict';
|
||||
const common = require('../common');
|
||||
const assert = require('assert');
|
||||
const net = require('net');
|
||||
|
||||
{
|
||||
const fp = '/tmp/fadagagsdfgsdf';
|
||||
const c = net.connect(fp);
|
||||
|
||||
c.on('connect', common.mustNotCall());
|
||||
c.on('error', common.expectsError({
|
||||
code: 'ENOENT',
|
||||
message: `connect ENOENT ${fp}`
|
||||
}));
|
||||
}
|
||||
|
||||
{
|
||||
assert.throws(
|
||||
() => net.createConnection({ path: {} }),
|
||||
{ code: 'ERR_INVALID_ARG_TYPE' }
|
||||
);
|
||||
}
|
||||
78
test/js/node/test/parallel/test-net-bytes-stats.js
Normal file
78
test/js/node/test/parallel/test-net-bytes-stats.js
Normal file
@@ -0,0 +1,78 @@
|
||||
// Copyright Joyent, Inc. and other Node contributors.
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a
|
||||
// copy of this software and associated documentation files (the
|
||||
// "Software"), to deal in the Software without restriction, including
|
||||
// without limitation the rights to use, copy, modify, merge, publish,
|
||||
// distribute, sublicense, and/or sell copies of the Software, and to permit
|
||||
// persons to whom the Software is furnished to do so, subject to the
|
||||
// following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included
|
||||
// in all copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
|
||||
// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN
|
||||
// NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
|
||||
// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
|
||||
// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
|
||||
// USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
|
||||
'use strict';
|
||||
require('../common');
|
||||
const assert = require('assert');
|
||||
const net = require('net');
|
||||
|
||||
let bytesRead = 0;
|
||||
let bytesWritten = 0;
|
||||
let count = 0;
|
||||
|
||||
const tcp = net.Server(function(s) {
|
||||
console.log('tcp server connection');
|
||||
|
||||
// trigger old mode.
|
||||
s.resume();
|
||||
|
||||
s.on('end', function() {
|
||||
bytesRead += s.bytesRead;
|
||||
console.log(`tcp socket disconnect #${count}`);
|
||||
});
|
||||
});
|
||||
|
||||
tcp.listen(0, function doTest() {
|
||||
console.error('listening');
|
||||
const socket = net.createConnection(this.address().port);
|
||||
|
||||
socket.on('connect', function() {
|
||||
count++;
|
||||
console.error('CLIENT connect #%d', count);
|
||||
|
||||
socket.write('foo', function() {
|
||||
console.error('CLIENT: write cb');
|
||||
socket.end('bar');
|
||||
});
|
||||
});
|
||||
|
||||
socket.on('finish', function() {
|
||||
bytesWritten += socket.bytesWritten;
|
||||
console.error('CLIENT end event #%d', count);
|
||||
});
|
||||
|
||||
socket.on('close', function() {
|
||||
console.error('CLIENT close event #%d', count);
|
||||
console.log(`Bytes read: ${bytesRead}`);
|
||||
console.log(`Bytes written: ${bytesWritten}`);
|
||||
if (count < 2) {
|
||||
console.error('RECONNECTING');
|
||||
socket.connect(tcp.address().port);
|
||||
} else {
|
||||
tcp.close();
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
process.on('exit', function() {
|
||||
assert.strictEqual(bytesRead, 12);
|
||||
assert.strictEqual(bytesWritten, 12);
|
||||
});
|
||||
@@ -0,0 +1,44 @@
|
||||
import * as common from '../common/index.mjs';
|
||||
import net from 'node:net';
|
||||
import { describe, it } from 'node:test';
|
||||
|
||||
const brokenCustomLookup = (_hostname, options, callback) => {
|
||||
// Incorrectly return an array of IPs instead of a string.
|
||||
callback(null, ['127.0.0.1'], options.family);
|
||||
};
|
||||
|
||||
describe('when family is ipv4', () => {
|
||||
it('socket emits an error when lookup does not return a string', (t, done) => {
|
||||
const options = {
|
||||
host: 'example.com',
|
||||
port: 80,
|
||||
lookup: brokenCustomLookup,
|
||||
family: 4
|
||||
};
|
||||
|
||||
const socket = net.connect(options, common.mustNotCall());
|
||||
socket.on('error', (err) => {
|
||||
t.assert.strictEqual(err.code, 'ERR_INVALID_IP_ADDRESS');
|
||||
|
||||
done();
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe('when family is ipv6', () => {
|
||||
it('socket emits an error when lookup does not return a string', (t, done) => {
|
||||
const options = {
|
||||
host: 'example.com',
|
||||
port: 80,
|
||||
lookup: brokenCustomLookup,
|
||||
family: 6
|
||||
};
|
||||
|
||||
const socket = net.connect(options, common.mustNotCall());
|
||||
socket.on('error', (err) => {
|
||||
t.assert.strictEqual(err.code, 'ERR_INVALID_IP_ADDRESS');
|
||||
|
||||
done();
|
||||
});
|
||||
});
|
||||
});
|
||||
55
test/js/node/test/parallel/test-net-connect-keepalive.js
Normal file
55
test/js/node/test/parallel/test-net-connect-keepalive.js
Normal file
@@ -0,0 +1,55 @@
|
||||
'use strict';
|
||||
const common = require('../common');
|
||||
const assert = require('assert');
|
||||
const net = require('net');
|
||||
|
||||
const truthyValues = [true, 1, 'true', {}, []];
|
||||
const delays = [[123, 0], [456123, 456], [-123000, 0], [undefined, 0]];
|
||||
const falseyValues = [false, 0, ''];
|
||||
|
||||
const genSetKeepAlive = (desiredEnable, desiredDelay) => (enable, delay) => {
|
||||
assert.strictEqual(enable, desiredEnable);
|
||||
assert.strictEqual(delay, desiredDelay);
|
||||
};
|
||||
|
||||
for (const value of truthyValues) {
|
||||
for (const delay of delays) {
|
||||
const server = net.createServer();
|
||||
|
||||
server.listen(0, common.mustCall(function() {
|
||||
const port = server.address().port;
|
||||
|
||||
const client = net.connect(
|
||||
{ port, keepAlive: value, keepAliveInitialDelay: delay[0] },
|
||||
common.mustCall(() => client.end())
|
||||
);
|
||||
|
||||
client._handle.setKeepAlive = common.mustCall(
|
||||
genSetKeepAlive(true, delay[1])
|
||||
);
|
||||
|
||||
client.on('end', common.mustCall(function() {
|
||||
server.close();
|
||||
}));
|
||||
}));
|
||||
}
|
||||
}
|
||||
|
||||
for (const value of falseyValues) {
|
||||
const server = net.createServer();
|
||||
|
||||
server.listen(0, common.mustCall(function() {
|
||||
const port = server.address().port;
|
||||
|
||||
const client = net.connect(
|
||||
{ port, keepAlive: value },
|
||||
common.mustCall(() => client.end())
|
||||
);
|
||||
|
||||
client._handle.setKeepAlive = common.mustNotCall();
|
||||
|
||||
client.on('end', common.mustCall(function() {
|
||||
server.close();
|
||||
}));
|
||||
}));
|
||||
}
|
||||
59
test/js/node/test/parallel/test-net-connect-memleak.js
Normal file
59
test/js/node/test/parallel/test-net-connect-memleak.js
Normal file
@@ -0,0 +1,59 @@
|
||||
// Copyright Joyent, Inc. and other Node contributors.
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a
|
||||
// copy of this software and associated documentation files (the
|
||||
// "Software"), to deal in the Software without restriction, including
|
||||
// without limitation the rights to use, copy, modify, merge, publish,
|
||||
// distribute, sublicense, and/or sell copies of the Software, and to permit
|
||||
// persons to whom the Software is furnished to do so, subject to the
|
||||
// following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included
|
||||
// in all copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
|
||||
// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN
|
||||
// NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
|
||||
// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
|
||||
// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
|
||||
// USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
|
||||
'use strict';
|
||||
// Flags: --expose-gc
|
||||
|
||||
const common = require('../common');
|
||||
if (require("./../../../../harness").isASAN) return;
|
||||
const { onGC } = require('../common/gc');
|
||||
const assert = require('assert');
|
||||
const net = require('net');
|
||||
|
||||
// Test that the implicit listener for an 'connect' event on net.Sockets is
|
||||
// added using `once()`, i.e. can be gc'ed once that event has occurred.
|
||||
|
||||
const server = net.createServer(common.mustCall()).listen(0);
|
||||
|
||||
let collected = false;
|
||||
const gcListener = { ongc() { collected = true; } };
|
||||
|
||||
{
|
||||
const gcObject = {};
|
||||
onGC(gcObject, gcListener);
|
||||
|
||||
const sock = net.createConnection(
|
||||
server.address().port,
|
||||
common.mustCall(() => {
|
||||
assert.strictEqual(gcObject, gcObject); // Keep reference alive
|
||||
assert.strictEqual(collected, false);
|
||||
setImmediate(done, sock);
|
||||
}));
|
||||
}
|
||||
|
||||
function done(sock) {
|
||||
globalThis.gc(true);
|
||||
setImmediate(() => {
|
||||
assert.strictEqual(collected, true);
|
||||
sock.end();
|
||||
server.close();
|
||||
});
|
||||
}
|
||||
@@ -5,31 +5,31 @@ const assert = require('assert');
|
||||
const net = require('net');
|
||||
|
||||
// Tests that net.connect() called without arguments throws ERR_MISSING_ARGS.
|
||||
const message = 'The "options", "port", or "path" argument must be specified';
|
||||
|
||||
assert.throws(() => {
|
||||
net.connect();
|
||||
}, {
|
||||
code: 'ERR_MISSING_ARGS',
|
||||
message,
|
||||
message: 'The "options" or "port" or "path" argument must be specified',
|
||||
});
|
||||
|
||||
assert.throws(() => {
|
||||
new net.Socket().connect();
|
||||
}, {
|
||||
code: 'ERR_MISSING_ARGS',
|
||||
message,
|
||||
message: 'The "options" or "port" or "path" argument must be specified',
|
||||
});
|
||||
|
||||
assert.throws(() => {
|
||||
net.connect({});
|
||||
}, {
|
||||
code: 'ERR_MISSING_ARGS',
|
||||
message,
|
||||
message: 'The "options" or "port" or "path" argument must be specified',
|
||||
});
|
||||
|
||||
assert.throws(() => {
|
||||
new net.Socket().connect({});
|
||||
}, {
|
||||
code: 'ERR_MISSING_ARGS',
|
||||
message,
|
||||
message: 'The "options" or "port" or "path" argument must be specified',
|
||||
});
|
||||
|
||||
@@ -25,3 +25,16 @@ const net = require('net');
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
{
|
||||
assert.throws(() => {
|
||||
net.createConnection({
|
||||
host: ['192.168.0.1'],
|
||||
port: 8080,
|
||||
});
|
||||
}, {
|
||||
code: 'ERR_INVALID_ARG_TYPE',
|
||||
name: 'TypeError',
|
||||
message: 'The "options.host" property must be of type string. Received an instance of Array',
|
||||
});
|
||||
}
|
||||
|
||||
33
test/js/node/test/parallel/test-net-listen-fd0.js
Normal file
33
test/js/node/test/parallel/test-net-listen-fd0.js
Normal file
@@ -0,0 +1,33 @@
|
||||
// Copyright Joyent, Inc. and other Node contributors.
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a
|
||||
// copy of this software and associated documentation files (the
|
||||
// "Software"), to deal in the Software without restriction, including
|
||||
// without limitation the rights to use, copy, modify, merge, publish,
|
||||
// distribute, sublicense, and/or sell copies of the Software, and to permit
|
||||
// persons to whom the Software is furnished to do so, subject to the
|
||||
// following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included
|
||||
// in all copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
|
||||
// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN
|
||||
// NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
|
||||
// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
|
||||
// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
|
||||
// USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
|
||||
'use strict';
|
||||
const common = require('../common');
|
||||
const assert = require('assert');
|
||||
const net = require('net');
|
||||
|
||||
// This should fail with an async EINVAL error, not throw an exception
|
||||
net.createServer(common.mustNotCall())
|
||||
.listen({ fd: 0 })
|
||||
.on('error', common.mustCall(function(e) {
|
||||
assert(e instanceof Error);
|
||||
assert(['EINVAL', 'ENOTSOCK'].includes(e.code));
|
||||
}));
|
||||
98
test/js/node/test/parallel/test-net-pipe-connect-errors.js
Normal file
98
test/js/node/test/parallel/test-net-pipe-connect-errors.js
Normal file
@@ -0,0 +1,98 @@
|
||||
// Copyright Joyent, Inc. and other Node contributors.
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a
|
||||
// copy of this software and associated documentation files (the
|
||||
// "Software"), to deal in the Software without restriction, including
|
||||
// without limitation the rights to use, copy, modify, merge, publish,
|
||||
// distribute, sublicense, and/or sell copies of the Software, and to permit
|
||||
// persons to whom the Software is furnished to do so, subject to the
|
||||
// following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included
|
||||
// in all copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
|
||||
// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN
|
||||
// NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
|
||||
// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
|
||||
// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
|
||||
// USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
|
||||
'use strict';
|
||||
const common = require('../common');
|
||||
if (common.isWindows) return; // TODO: BUN use better WSA api, 'connect' always returns ECONNREFUSED.
|
||||
const fixtures = require('../common/fixtures');
|
||||
const fs = require('fs');
|
||||
const net = require('net');
|
||||
const assert = require('assert');
|
||||
|
||||
// Test if ENOTSOCK is fired when trying to connect to a file which is not
|
||||
// a socket.
|
||||
|
||||
let emptyTxt;
|
||||
|
||||
if (common.isWindows) {
|
||||
// On Win, common.PIPE will be a named pipe, so we use an existing empty
|
||||
// file instead
|
||||
emptyTxt = fixtures.path('empty.txt');
|
||||
} else {
|
||||
const tmpdir = require('../common/tmpdir');
|
||||
tmpdir.refresh();
|
||||
// Keep the file name very short so that we don't exceed the 108 char limit
|
||||
// on CI for a POSIX socket. Even though this isn't actually a socket file,
|
||||
// the error will be different from the one we are expecting if we exceed the
|
||||
// limit.
|
||||
emptyTxt = `${tmpdir.path}0.txt`;
|
||||
|
||||
function cleanup() {
|
||||
try {
|
||||
fs.unlinkSync(emptyTxt);
|
||||
} catch (e) {
|
||||
assert.strictEqual(e.code, 'ENOENT');
|
||||
}
|
||||
}
|
||||
process.on('exit', cleanup);
|
||||
cleanup();
|
||||
fs.writeFileSync(emptyTxt, '');
|
||||
}
|
||||
|
||||
const notSocketClient = net.createConnection(emptyTxt, function() {
|
||||
assert.fail('connection callback should not run');
|
||||
});
|
||||
|
||||
notSocketClient.on('error', common.mustCall(function(err) {
|
||||
assert(err.code === 'ENOTSOCK' || err.code === 'ECONNREFUSED',
|
||||
`received ${err.code} instead of ENOTSOCK or ECONNREFUSED`);
|
||||
}));
|
||||
|
||||
|
||||
// Trying to connect to not-existing socket should result in ENOENT error
|
||||
const noEntSocketClient = net.createConnection('no-ent-file', function() {
|
||||
assert.fail('connection to non-existent socket, callback should not run');
|
||||
});
|
||||
|
||||
noEntSocketClient.on('error', common.mustCall(function(err) {
|
||||
assert.strictEqual(err.code, 'ENOENT');
|
||||
}));
|
||||
|
||||
|
||||
// On Windows or IBMi or when running as root,
|
||||
// a chmod has no effect on named pipes
|
||||
if (!common.isWindows && !common.isIBMi && process.getuid() !== 0) {
|
||||
// Trying to connect to a socket one has no access to should result in EACCES
|
||||
const accessServer = net.createServer(
|
||||
common.mustNotCall('server callback should not run'));
|
||||
accessServer.listen(common.PIPE, common.mustCall(function() {
|
||||
fs.chmodSync(common.PIPE, 0);
|
||||
|
||||
const accessClient = net.createConnection(common.PIPE, function() {
|
||||
assert.fail('connection should get EACCES, callback should not run');
|
||||
});
|
||||
|
||||
accessClient.on('error', common.mustCall(function(err) {
|
||||
assert.strictEqual(err.code, 'EACCES');
|
||||
accessServer.close();
|
||||
}));
|
||||
}));
|
||||
}
|
||||
36
test/js/node/test/parallel/test-net-pipe-with-long-path.js
Normal file
36
test/js/node/test/parallel/test-net-pipe-with-long-path.js
Normal file
@@ -0,0 +1,36 @@
|
||||
'use strict';
|
||||
const common = require('../common');
|
||||
const assert = require('assert');
|
||||
const net = require('net');
|
||||
const fs = require('fs');
|
||||
const tmpdir = require('../common/tmpdir');
|
||||
tmpdir.refresh();
|
||||
|
||||
// Test UV_PIPE_NO_TRUNCATE
|
||||
|
||||
// See pipe_overlong_path in https://github.com/libuv/libuv/blob/master/test/test-pipe-bind-error.c
|
||||
if (common.isWindows) {
|
||||
common.skip('UV_PIPE_NO_TRUNCATE is not supported on window');
|
||||
}
|
||||
|
||||
// See https://github.com/libuv/libuv/issues/4231
|
||||
const pipePath = `${tmpdir.path}/${'x'.repeat(10000)}.sock`;
|
||||
|
||||
const server = net.createServer()
|
||||
.listen(pipePath)
|
||||
// It may work on some operating systems
|
||||
.on('listening', () => {
|
||||
// The socket file must exist
|
||||
assert.ok(fs.existsSync(pipePath));
|
||||
const socket = net.connect(pipePath, common.mustCall(() => {
|
||||
socket.destroy();
|
||||
server.close();
|
||||
}));
|
||||
})
|
||||
.on('error', (error) => {
|
||||
assert.ok(error.code === 'EINVAL');
|
||||
net.connect(pipePath)
|
||||
.on('error', common.mustCall((error) => {
|
||||
assert.ok(error.code === 'EINVAL');
|
||||
}));
|
||||
});
|
||||
@@ -0,0 +1,27 @@
|
||||
'use strict';
|
||||
|
||||
const common = require('../common');
|
||||
const assert = require('assert');
|
||||
const events = require('events');
|
||||
const { createServer, connect } = require('net');
|
||||
|
||||
events.captureRejections = true;
|
||||
|
||||
const server = createServer(common.mustCall(async (sock) => {
|
||||
server.close();
|
||||
|
||||
const _err = new Error('kaboom');
|
||||
sock.on('error', common.mustCall((err) => {
|
||||
assert.strictEqual(err, _err);
|
||||
}));
|
||||
throw _err;
|
||||
}));
|
||||
|
||||
server.listen(0, common.mustCall(() => {
|
||||
const sock = connect(
|
||||
server.address().port,
|
||||
server.address().host
|
||||
);
|
||||
|
||||
sock.on('close', common.mustCall());
|
||||
}));
|
||||
@@ -0,0 +1,42 @@
|
||||
'use strict';
|
||||
const common = require('../common');
|
||||
const assert = require('assert');
|
||||
const net = require('net');
|
||||
|
||||
{
|
||||
const server = net.createServer();
|
||||
|
||||
server.listen(common.mustCall(() => {
|
||||
const port = server.address().port;
|
||||
const client = net.connect({ port }, common.mustCall(() => {
|
||||
client.on('error', common.mustCall((err) => {
|
||||
server.close();
|
||||
assert.strictEqual(err.constructor, Error);
|
||||
assert.strictEqual(err.message, 'write EBADF');
|
||||
}));
|
||||
client._handle.close();
|
||||
client.write('foo');
|
||||
}));
|
||||
}));
|
||||
}
|
||||
|
||||
{
|
||||
const server = net.createServer();
|
||||
|
||||
server.listen(common.mustCall(() => {
|
||||
const port = server.address().port;
|
||||
const client = net.connect({ port }, common.mustCall(() => {
|
||||
client.on('error', common.expectsError({
|
||||
code: 'ERR_SOCKET_CLOSED',
|
||||
message: 'Socket is closed',
|
||||
name: 'Error'
|
||||
}));
|
||||
|
||||
server.close();
|
||||
|
||||
client._handle.close();
|
||||
client._handle = null;
|
||||
client.write('foo');
|
||||
}));
|
||||
}));
|
||||
}
|
||||
51
test/js/node/test/parallel/test-net-stream.js
Normal file
51
test/js/node/test/parallel/test-net-stream.js
Normal file
@@ -0,0 +1,51 @@
|
||||
// Copyright Joyent, Inc. and other Node contributors.
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a
|
||||
// copy of this software and associated documentation files (the
|
||||
// "Software"), to deal in the Software without restriction, including
|
||||
// without limitation the rights to use, copy, modify, merge, publish,
|
||||
// distribute, sublicense, and/or sell copies of the Software, and to permit
|
||||
// persons to whom the Software is furnished to do so, subject to the
|
||||
// following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included
|
||||
// in all copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
|
||||
// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN
|
||||
// NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
|
||||
// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
|
||||
// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
|
||||
// USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
|
||||
'use strict';
|
||||
|
||||
const common = require('../common');
|
||||
const assert = require('assert');
|
||||
const net = require('net');
|
||||
|
||||
const SIZE = 2E6;
|
||||
const N = 10;
|
||||
const buf = Buffer.alloc(SIZE, 'a');
|
||||
|
||||
const server = net.createServer(function(socket) {
|
||||
socket.setNoDelay();
|
||||
|
||||
socket.on('error', common.mustCall(() => socket.destroy()))
|
||||
.on('close', common.mustCall(() => server.close()));
|
||||
|
||||
for (let i = 0; i < N; ++i) {
|
||||
socket.write(buf, () => {});
|
||||
}
|
||||
socket.end();
|
||||
|
||||
}).listen(0, function() {
|
||||
const conn = net.connect(this.address().port);
|
||||
conn.on('data', function(buf) {
|
||||
assert.strictEqual(conn, conn.pause());
|
||||
setTimeout(function() {
|
||||
conn.destroy();
|
||||
}, 20);
|
||||
});
|
||||
});
|
||||
@@ -6,35 +6,6 @@ import { request } from "http";
|
||||
import { join } from "path";
|
||||
const tmp_dir = tmpdirSync();
|
||||
|
||||
it("throws ENAMETOOLONG when socket path exceeds platform-specific limit", () => {
|
||||
// this must be the filename specifically, because we add a workaround for the length limit on linux
|
||||
const path = "a".repeat(
|
||||
{
|
||||
darwin: 104,
|
||||
linux: 108,
|
||||
win32: 260,
|
||||
sunos: 104,
|
||||
aix: 104,
|
||||
freebsd: 104,
|
||||
openbsd: 104,
|
||||
netbsd: 104,
|
||||
plan9: 104,
|
||||
android: 104,
|
||||
haiku: 104,
|
||||
cygwin: 260,
|
||||
}[process.platform],
|
||||
);
|
||||
|
||||
expect(() =>
|
||||
serve({
|
||||
unix: path,
|
||||
fetch(req) {
|
||||
return new Response("hello");
|
||||
},
|
||||
}),
|
||||
).toThrow("too long");
|
||||
});
|
||||
|
||||
it("throws an error when the directory is not found", () => {
|
||||
// this must be the filename specifically, because we add a workaround for the length limit on linux
|
||||
const unix = isWindows
|
||||
|
||||
Reference in New Issue
Block a user