mirror of
https://github.com/oven-sh/bun
synced 2026-02-06 00:48:55 +00:00
Compare commits
8 Commits
dylan/pyth
...
nektro-pat
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
72031eeafc | ||
|
|
05f102ee58 | ||
|
|
609b575500 | ||
|
|
1a0e3b22a8 | ||
|
|
32c8e541d6 | ||
|
|
f312e9ad30 | ||
|
|
d923684b4a | ||
|
|
eed648e28f |
@@ -600,7 +600,7 @@ function getTestBunStep(platform, options, testOptions = {}) {
|
||||
retry: getRetry(),
|
||||
cancel_on_build_failing: isMergeQueue(),
|
||||
parallelism: unifiedTests ? undefined : os === "darwin" ? 2 : 10,
|
||||
timeout_in_minutes: profile === "asan" || os === "windows" ? 45 : 30,
|
||||
timeout_in_minutes: 60,
|
||||
command:
|
||||
os === "windows"
|
||||
? `node .\\scripts\\runner.node.mjs ${args.join(" ")}`
|
||||
|
||||
@@ -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);
|
||||
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, error);
|
||||
if (written == header_length) {
|
||||
ssize_t second_write = bsd_send(fd, payload, payload_length);
|
||||
ssize_t second_write = bsd_send(fd, payload, payload_length, 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) {
|
||||
ssize_t bsd_send(LIBUS_SOCKET_DESCRIPTOR fd, const char *buf, int length, int *error) {
|
||||
while (1) {
|
||||
// MSG_MORE (Linux), MSG_PARTIAL (Windows), TCP_NOPUSH (BSD)
|
||||
|
||||
@@ -787,6 +790,10 @@ ssize_t bsd_send(LIBUS_SOCKET_DESCRIPTOR fd, const char *buf, int length) {
|
||||
if (UNLIKELY(IS_EINTR(rc))) {
|
||||
continue;
|
||||
}
|
||||
if (rc < 0) {
|
||||
if (error != NULL) *error = LIBUS_ERR;
|
||||
return -1;
|
||||
}
|
||||
|
||||
return rc;
|
||||
}
|
||||
@@ -819,16 +826,18 @@ static int us_internal_bind_and_listen(LIBUS_SOCKET_DESCRIPTOR listenFd, struct
|
||||
do
|
||||
result = bind(listenFd, listenAddr, listenAddrLength);
|
||||
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;
|
||||
}
|
||||
@@ -951,7 +960,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;
|
||||
}
|
||||
@@ -968,7 +977,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;
|
||||
}
|
||||
@@ -996,7 +1005,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;
|
||||
|
||||
@@ -1005,7 +1014,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;
|
||||
}
|
||||
@@ -1024,13 +1033,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;
|
||||
}
|
||||
|
||||
@@ -1039,14 +1048,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 = EINVAL;
|
||||
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) {
|
||||
close(socket_dir_fd);
|
||||
errno = ENAMETOOLONG;
|
||||
if (error != NULL) *error = EINVAL;
|
||||
return LIBUS_SOCKET_ERROR;
|
||||
}
|
||||
|
||||
@@ -1069,7 +1078,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;
|
||||
@@ -1082,7 +1094,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;
|
||||
@@ -1114,7 +1126,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;
|
||||
}
|
||||
|
||||
@@ -1225,11 +1237,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);
|
||||
@@ -1328,7 +1336,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) {
|
||||
@@ -1347,6 +1355,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;
|
||||
}
|
||||
}
|
||||
@@ -1367,7 +1376,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;
|
||||
@@ -1409,8 +1419,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;
|
||||
}
|
||||
@@ -1447,7 +1457,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);
|
||||
@@ -1456,8 +1466,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;
|
||||
@@ -1465,7 +1475,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;
|
||||
}
|
||||
@@ -1473,15 +1483,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) {
|
||||
|
||||
@@ -430,8 +430,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;
|
||||
}
|
||||
@@ -501,10 +501,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
|
||||
|
||||
@@ -514,7 +514,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;
|
||||
@@ -534,7 +534,7 @@ void *us_socket_context_connect(int ssl, struct us_socket_context_t *context, co
|
||||
struct sockaddr_storage addr;
|
||||
init_addr_with_port(&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;
|
||||
}
|
||||
@@ -566,7 +566,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;
|
||||
}
|
||||
@@ -655,6 +655,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;
|
||||
}
|
||||
}
|
||||
@@ -733,14 +735,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;
|
||||
}
|
||||
|
||||
@@ -135,7 +135,7 @@ int BIO_s_custom_write(BIO *bio, const char *data, int length) {
|
||||
struct loop_ssl_data *loop_ssl_data =
|
||||
(struct loop_ssl_data *)BIO_get_data(bio);
|
||||
|
||||
int written = us_socket_write(0, loop_ssl_data->ssl_socket, data, length);
|
||||
int written = us_socket_write(0, loop_ssl_data->ssl_socket, data, length, NULL);
|
||||
|
||||
BIO_clear_retry_flags(bio);
|
||||
if (!written) {
|
||||
@@ -1608,11 +1608,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 +1621,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);
|
||||
}
|
||||
@@ -1746,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);
|
||||
return us_socket_write(0, &s->s, data, length, 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)
|
||||
@@ -410,11 +411,12 @@ 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);
|
||||
|
||||
@@ -210,11 +210,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);
|
||||
ssize_t bsd_send(LIBUS_SOCKET_DESCRIPTOR fd, const char *buf, int length, 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 +228,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
|
||||
|
||||
@@ -328,10 +328,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. */
|
||||
int us_socket_write(int ssl, us_socket_r s, const char * nonnull_arg data, int length) nonnull_fn_decl;
|
||||
int us_socket_write(int ssl, us_socket_r s, const char * nonnull_arg data, int length, 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 * nonnull_arg header, int header_length, const char * nonnull_arg 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 */
|
||||
|
||||
@@ -307,7 +307,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 us_socket_write(int ssl, struct us_socket_t *s, const char *data, int length, int *error) {
|
||||
#ifndef LIBUS_NO_SSL
|
||||
if (ssl) {
|
||||
return us_internal_ssl_socket_write((struct us_internal_ssl_socket_t *) s, data, length);
|
||||
@@ -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);
|
||||
int written = bsd_send(us_poll_fd(&s->p), data, length, 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);
|
||||
return us_socket_write(ssl, s, data, length, 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);
|
||||
int written = us_socket_write(SSL, (us_socket_t *) this, asyncSocketData->buffer.data(), max_flush_len, 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);
|
||||
int written = us_socket_write(SSL, (us_socket_t *) this, asyncSocketData->buffer.data(), max_flush_len, 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);
|
||||
int written = us_socket_write(SSL, (us_socket_t *) this, src, length, NULL);
|
||||
|
||||
/* Did we fail? */
|
||||
if (written < length) {
|
||||
@@ -402,4 +402,4 @@ public:
|
||||
|
||||
}
|
||||
|
||||
#endif // UWS_ASYNCSOCKET_H
|
||||
#endif // UWS_ASYNCSOCKET_H
|
||||
|
||||
@@ -380,7 +380,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());
|
||||
us_socket_write(SSL, s, httpErrorResponses[httpErrorStatusCode].data(), (int) httpErrorResponses[httpErrorStatusCode].length(), NULL);
|
||||
us_socket_shutdown(SSL, s);
|
||||
/* Close any socket on HTTP errors */
|
||||
us_socket_close(SSL, s, 0, nullptr);
|
||||
|
||||
@@ -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 */
|
||||
@@ -380,4 +380,4 @@ public:
|
||||
|
||||
}
|
||||
|
||||
#endif // UWS_WEBSOCKET_H
|
||||
#endif // UWS_WEBSOCKET_H
|
||||
|
||||
@@ -2395,7 +2395,7 @@ pub const Resolver = 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()),
|
||||
};
|
||||
@@ -3101,7 +3101,7 @@ pub const Resolver = 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,
|
||||
|
||||
@@ -1523,7 +1523,10 @@ pub const H2FrameParser = struct {
|
||||
pub fn _genericFlush(this: *H2FrameParser, comptime T: type, socket: T) usize {
|
||||
const buffer = this.writeBuffer.slice()[this.writeBufferOffset..];
|
||||
if (buffer.len > 0) {
|
||||
const result: i32 = socket.writeMaybeCorked(buffer);
|
||||
const result: i32 = switch (socket.writeMaybeCorked(buffer)) {
|
||||
.result => |result| result,
|
||||
.err => 0,
|
||||
};
|
||||
const written: u32 = if (result < 0) 0 else @intCast(result);
|
||||
|
||||
if (written < buffer.len) {
|
||||
@@ -1554,7 +1557,10 @@ pub const H2FrameParser = struct {
|
||||
const buffer = this.writeBuffer.slice()[this.writeBufferOffset..];
|
||||
if (buffer.len > 0) {
|
||||
{
|
||||
const result: i32 = socket.writeMaybeCorked(buffer);
|
||||
const result: i32 = switch (socket.writeMaybeCorked(buffer)) {
|
||||
.result => |result| result,
|
||||
.err => 0,
|
||||
};
|
||||
const written: u32 = if (result < 0) 0 else @intCast(result);
|
||||
if (written < buffer.len) {
|
||||
this.writeBufferOffset += written;
|
||||
@@ -1571,7 +1577,10 @@ pub const H2FrameParser = struct {
|
||||
this.writeBufferOffset = 0;
|
||||
this.writeBuffer.len = 0;
|
||||
{
|
||||
const result: i32 = socket.writeMaybeCorked(bytes);
|
||||
const result: i32 = switch (socket.writeMaybeCorked(bytes)) {
|
||||
.result => |result| result,
|
||||
.err => 0,
|
||||
};
|
||||
const written: u32 = if (result < 0) 0 else @intCast(result);
|
||||
if (written < bytes.len) {
|
||||
const pending = bytes[written..];
|
||||
@@ -1591,7 +1600,10 @@ pub const H2FrameParser = struct {
|
||||
}
|
||||
return true;
|
||||
}
|
||||
const result: i32 = socket.writeMaybeCorked(bytes);
|
||||
const result: i32 = switch (socket.writeMaybeCorked(bytes)) {
|
||||
.result => |result| result,
|
||||
.err => 0,
|
||||
};
|
||||
const written: u32 = if (result < 0) 0 else @intCast(result);
|
||||
if (written < bytes.len) {
|
||||
const pending = bytes[written..];
|
||||
|
||||
@@ -108,7 +108,7 @@ pub 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();
|
||||
@@ -121,6 +121,7 @@ pub fn NewSocket(comptime ssl: bool) type {
|
||||
this.socket_context.?,
|
||||
this,
|
||||
this.flags.allow_half_open,
|
||||
error_,
|
||||
);
|
||||
},
|
||||
.unix => |u| {
|
||||
@@ -129,10 +130,14 @@ pub 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);
|
||||
},
|
||||
}
|
||||
@@ -235,7 +240,7 @@ pub fn NewSocket(comptime ssl: bool) type {
|
||||
}
|
||||
this.ref();
|
||||
defer this.deref();
|
||||
this.internalFlush();
|
||||
this.internalFlush(false) 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;
|
||||
@@ -299,15 +304,13 @@ pub 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_,
|
||||
.errno = errno_,
|
||||
.message = bun.String.static("Failed to connect"),
|
||||
.syscall = bun.String.static("connect"),
|
||||
.code = code_,
|
||||
@@ -857,9 +860,9 @@ pub fn NewSocket(comptime ssl: bool) type {
|
||||
return JSValue.jsNumber(this.socket.remotePort());
|
||||
}
|
||||
|
||||
pub fn writeMaybeCorked(this: *This, buffer: []const u8) i32 {
|
||||
pub fn writeMaybeCorked(this: *This, buffer: []const u8) bun.Maybe(i32, bun.sys.Error) {
|
||||
if (this.socket.isShutdown() or this.socket.isClosed()) {
|
||||
return -1;
|
||||
return .initResult(-1);
|
||||
}
|
||||
|
||||
// we don't cork yet but we might later
|
||||
@@ -870,15 +873,21 @@ pub fn NewSocket(comptime ssl: bool) type {
|
||||
const uwrote: usize = @intCast(@max(res, 0));
|
||||
this.bytes_written += uwrote;
|
||||
log("write({d}) = {d}", .{ buffer.len, res });
|
||||
return res;
|
||||
return .initResult(res);
|
||||
}
|
||||
}
|
||||
|
||||
const res = this.socket.write(buffer);
|
||||
const res = switch (this.socket.writeMaybe(buffer)) {
|
||||
.result => |result| result,
|
||||
.err => |err| {
|
||||
if (err.errno == bun.sys.SystemErrno.EPIPE.to_uv_errno()) this.closeAndDetach(.normal);
|
||||
return .initErr(err);
|
||||
},
|
||||
};
|
||||
const uwrote: usize = @intCast(@max(res, 0));
|
||||
this.bytes_written += uwrote;
|
||||
log("write({d}) = {d}", .{ buffer.len, res });
|
||||
return res;
|
||||
return .initResult(res);
|
||||
}
|
||||
|
||||
pub fn writeBuffered(this: *This, globalObject: *jsc.JSGlobalObject, callframe: *jsc.CallFrame) bun.JSError!JSValue {
|
||||
@@ -894,9 +903,9 @@ pub fn NewSocket(comptime ssl: bool) type {
|
||||
return globalObject.throwValue(err.toErrorInstance(globalObject));
|
||||
}
|
||||
|
||||
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,
|
||||
};
|
||||
@@ -915,7 +924,7 @@ pub fn NewSocket(comptime ssl: bool) type {
|
||||
.fail => .zero,
|
||||
.success => |result| brk: {
|
||||
if (result.wrote == result.total) {
|
||||
this.internalFlush();
|
||||
this.internalFlush(true) catch return .false;
|
||||
}
|
||||
|
||||
break :brk JSValue.jsBoolean(@as(usize, @max(result.wrote, 0)) == result.total);
|
||||
@@ -983,7 +992,7 @@ pub 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) {
|
||||
@@ -1013,7 +1022,10 @@ pub fn NewSocket(comptime ssl: bool) type {
|
||||
|
||||
// slower-path: clone the data, do one write.
|
||||
bun.handleOom(this.buffered_data_for_node_net.append(bun.default_allocator, buffer.slice()));
|
||||
const rc = this.writeMaybeCorked(this.buffered_data_for_node_net.slice());
|
||||
const rc = switch (this.writeMaybeCorked(this.buffered_data_for_node_net.slice())) {
|
||||
.result => |result| result,
|
||||
.err => 0,
|
||||
};
|
||||
if (rc > 0) {
|
||||
const wrote: usize = @intCast(@max(rc, 0));
|
||||
// did we write everything?
|
||||
@@ -1161,7 +1173,10 @@ pub fn NewSocket(comptime ssl: bool) type {
|
||||
return .{ .success = .{} };
|
||||
}
|
||||
log("writeOrEnd {d}", .{bytes.len});
|
||||
const wrote = this.writeMaybeCorked(bytes);
|
||||
const wrote = switch (this.writeMaybeCorked(bytes)) {
|
||||
.result => |result| result,
|
||||
.err => 0,
|
||||
};
|
||||
const uwrote: usize = @intCast(@max(wrote, 0));
|
||||
if (buffer_unwritten_data) {
|
||||
const remaining = bytes[uwrote..];
|
||||
@@ -1193,19 +1208,27 @@ pub 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, is_end: bool) 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()), 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())) {
|
||||
.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| {
|
||||
if (!is_end) {
|
||||
this.handleError(err.toSystemError().toErrorInstance(this.handlers.?.globalObject));
|
||||
return error.CalledOnError;
|
||||
}
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1219,7 +1242,7 @@ pub 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(false) catch return .js_undefined;
|
||||
return .js_undefined;
|
||||
}
|
||||
|
||||
@@ -1267,7 +1290,7 @@ pub fn NewSocket(comptime ssl: bool) type {
|
||||
.fail => .zero,
|
||||
.success => |result| brk: {
|
||||
if (result.wrote == result.total) {
|
||||
this.internalFlush();
|
||||
this.internalFlush(true) catch return .jsNumber(0);
|
||||
}
|
||||
break :brk JSValue.jsNumber(result.wrote);
|
||||
},
|
||||
@@ -1850,7 +1873,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());
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1883,7 +1906,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);
|
||||
|
||||
|
||||
@@ -772,8 +772,11 @@ pub fn connectInner(globalObject: *jsc.JSGlobalObject, prev_maybe_tcp: ?*TCPSock
|
||||
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;
|
||||
};
|
||||
|
||||
|
||||
@@ -1392,7 +1392,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 => {
|
||||
@@ -1410,7 +1410,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));
|
||||
}
|
||||
},
|
||||
@@ -1530,12 +1530,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);
|
||||
}
|
||||
@@ -1747,7 +1742,7 @@ fn throwCommandNotFound(globalThis: *jsc.JSGlobalObject, command: []const u8) bu
|
||||
const err = jsc.SystemError{
|
||||
.message = bun.handleOom(bun.String.createFormat("Executable not found in $PATH: \"{s}\"", .{command})),
|
||||
.code = bun.String.static("ENOENT"),
|
||||
.errno = -bun.sys.UV_E.NOENT,
|
||||
.errno = bun.sys.UV_E.NOENT,
|
||||
.path = bun.String.cloneUTF8(command),
|
||||
};
|
||||
return globalThis.throwValue(err.toErrorInstance(globalThis));
|
||||
|
||||
@@ -319,9 +319,10 @@ pub const UDPSocket = struct {
|
||||
this.closed = true;
|
||||
defer this.deinit();
|
||||
if (err != 0) {
|
||||
const code = @tagName(bun.sys.SystemErrno.init(@as(c_int, @intCast(err))).?);
|
||||
const err_ = bun.sys.SystemErrno.init(@as(c_int, @intCast(err))).?;
|
||||
const code = @tagName(err_);
|
||||
const sys_err = jsc.SystemError{
|
||||
.errno = err,
|
||||
.errno = @intFromEnum(err_),
|
||||
.code = bun.String.static(code),
|
||||
.message = bun.handleOom(bun.String.createFormat("bind {s} {s}", .{ code, config.hostname })),
|
||||
};
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
pub const SystemError = extern struct {
|
||||
errno: c_int = 0,
|
||||
errno: c_uint = 0,
|
||||
/// label for errno
|
||||
code: String = .empty,
|
||||
message: String, // it is illegal to have an empty message
|
||||
@@ -22,7 +22,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 {
|
||||
|
||||
@@ -4,7 +4,7 @@ pub const ZigException = extern struct {
|
||||
runtime_type: JSRuntimeType,
|
||||
|
||||
/// SystemError only
|
||||
errno: c_int = 0,
|
||||
errno: c_uint = 0,
|
||||
/// SystemError only
|
||||
syscall: String = String.empty,
|
||||
/// SystemError only
|
||||
|
||||
@@ -2214,7 +2214,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(), jsNumber(err.errno_), JSC::PropertyAttribute::DontDelete | 0);
|
||||
result->putDirect(vm, names.errnoPublicName(), jsNumber(-static_cast<int>(err.errno_)), JSC::PropertyAttribute::DontDelete | 0);
|
||||
|
||||
ASSERT_NO_PENDING_EXCEPTION(globalObject);
|
||||
return JSC::JSValue::encode(result);
|
||||
@@ -2252,8 +2252,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(), jsNumber(err.errno_), JSC::PropertyAttribute::DontDelete | 0);
|
||||
info->putDirect(vm, clientData->builtinNames().errnoPublicName(), jsNumber(-static_cast<int>(err.errno_)), JSC::PropertyAttribute::DontDelete | 0);
|
||||
result->putDirect(vm, clientData->builtinNames().errnoPublicName(), jsNumber(-static_cast<int>(err.errno_)), JSC::PropertyAttribute::DontDelete | 0);
|
||||
|
||||
ASSERT_NO_PENDING_EXCEPTION(globalObject);
|
||||
return JSC::JSValue::encode(result);
|
||||
|
||||
@@ -130,7 +130,7 @@ typedef struct ErrorableResolvedSource {
|
||||
} ErrorableResolvedSource;
|
||||
|
||||
typedef struct SystemError {
|
||||
int errno_;
|
||||
unsigned int errno_;
|
||||
BunString code;
|
||||
BunString message;
|
||||
BunString path;
|
||||
@@ -197,7 +197,7 @@ typedef struct ZigStackTrace {
|
||||
typedef struct ZigException {
|
||||
unsigned char type;
|
||||
uint16_t runtime_type;
|
||||
int errno_;
|
||||
unsigned int errno_;
|
||||
BunString syscall;
|
||||
BunString system_code;
|
||||
BunString path;
|
||||
|
||||
@@ -291,8 +291,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"),
|
||||
};
|
||||
@@ -642,11 +642,12 @@ 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) {
|
||||
bun.assert(err < 0);
|
||||
const sys_err = jsc.SystemError{
|
||||
.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));
|
||||
@@ -814,8 +815,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"),
|
||||
};
|
||||
@@ -826,8 +827,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"),
|
||||
};
|
||||
@@ -838,8 +839,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"),
|
||||
};
|
||||
@@ -886,19 +887,12 @@ 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);
|
||||
// uv_uptime cannot fail on windows
|
||||
return uptime_value;
|
||||
},
|
||||
.mac => {
|
||||
|
||||
@@ -1637,7 +1637,7 @@ pub const ARES_ECANCELLED = 24;
|
||||
pub const ARES_ESERVICE = 25;
|
||||
pub const ARES_ENOSERVER = 26;
|
||||
|
||||
pub const Error = enum(i32) {
|
||||
pub const Error = enum(u16) {
|
||||
ENODATA = ARES_ENODATA,
|
||||
EFORMERR = ARES_EFORMERR,
|
||||
ESERVFAIL = ARES_ESERVFAIL,
|
||||
|
||||
@@ -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) bun.Maybe(i32, bun.sys.Error) {
|
||||
return switch (this.socket) {
|
||||
.upgradedDuplex => |socket| .initResult(socket.encodeAndWrite(data)),
|
||||
.pipe => |pipe| .initResult(if (comptime Environment.isWindows) pipe.encodeAndWrite(data) else 0),
|
||||
.connected => |socket| socket.writeMaybe(is_ssl, data),
|
||||
.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),
|
||||
@@ -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_ = bun.handleOom(allocator.dupeZ(u8, path));
|
||||
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{
|
||||
|
||||
@@ -127,11 +127,19 @@ pub const us_socket_t = opaque {
|
||||
}
|
||||
|
||||
pub fn write(this: *us_socket_t, ssl: bool, data: []const u8) i32 {
|
||||
const rc = c.us_socket_write(@intFromBool(ssl), this, data.ptr, @intCast(data.len));
|
||||
const rc = c.us_socket_write(@intFromBool(ssl), this, data.ptr, @intCast(data.len), 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) bun.Maybe(i32, bun.sys.Error) {
|
||||
var error_: u32 = 0;
|
||||
const rc = c.us_socket_write(@intFromBool(ssl), this, data.ptr, @intCast(data.len), &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());
|
||||
@@ -139,8 +147,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_: ?*u32) 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;
|
||||
}
|
||||
@@ -198,9 +206,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) i32;
|
||||
pub extern fn us_socket_write(ssl: i32, s: ?*us_socket_t, data: [*c]const u8, length: i32, error_: ?*u32) 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, usize, payload: ?[*]const u8, usize, error_: ?*u32) i32;
|
||||
pub extern fn us_socket_raw_write(ssl: i32, s: ?*us_socket_t, data: [*c]const u8, length: i32) i32;
|
||||
pub extern fn us_socket_flush(ssl: i32, s: ?*us_socket_t) void;
|
||||
|
||||
@@ -218,12 +226,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);
|
||||
|
||||
@@ -1093,6 +1093,235 @@ 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,
|
||||
.UV_ENOEXEC => .UV_ENOEXEC,
|
||||
}));
|
||||
}
|
||||
};
|
||||
|
||||
pub const UV_E = struct {
|
||||
@@ -1167,6 +1396,56 @@ pub const UV_E = struct {
|
||||
pub const NOEXEC = -uv.UV_ENOEXEC;
|
||||
};
|
||||
|
||||
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}),
|
||||
});
|
||||
}
|
||||
|
||||
const bun = @import("bun");
|
||||
const std = @import("std");
|
||||
|
||||
|
||||
@@ -448,6 +448,7 @@ pub 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;
|
||||
@@ -482,6 +483,7 @@ pub fn NewHTTPContext(comptime ssl: bool) type {
|
||||
this.us_socket_context,
|
||||
ActiveSocket.init(client).ptr(),
|
||||
false,
|
||||
null,
|
||||
);
|
||||
client.allow_retry = false;
|
||||
return socket;
|
||||
|
||||
@@ -133,6 +133,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) {
|
||||
|
||||
@@ -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;
|
||||
@@ -477,7 +477,6 @@ const ServerHandlers: SocketHandler<NetSocket> = {
|
||||
if (!data) return;
|
||||
|
||||
if (data._hadError) return;
|
||||
data._hadError = true;
|
||||
const bunTLS = this[bunTlsSymbol];
|
||||
|
||||
if (typeof bunTLS === "function") {
|
||||
@@ -501,7 +500,6 @@ const ServerHandlers: SocketHandler<NetSocket> = {
|
||||
}
|
||||
}
|
||||
SocketHandlers.error(socket, error, true);
|
||||
data.server.emit("clientError", error, data);
|
||||
},
|
||||
timeout(socket) {
|
||||
SocketHandlers.timeout(socket);
|
||||
|
||||
@@ -914,7 +914,7 @@ pub fn call(globalObject: *jsc.JSGlobalObject, callframe: *jsc.CallFrame) bun.JS
|
||||
if (path.len > 0) {
|
||||
debug("connecting to mysql with path", .{});
|
||||
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);
|
||||
@@ -926,7 +926,7 @@ pub fn call(globalObject: *jsc.JSGlobalObject, callframe: *jsc.CallFrame) bun.JS
|
||||
} else {
|
||||
debug("connecting to mysql with hostname", .{});
|
||||
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);
|
||||
|
||||
@@ -734,7 +734,7 @@ pub fn call(globalObject: *jsc.JSGlobalObject, callframe: *jsc.CallFrame) bun.JS
|
||||
|
||||
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);
|
||||
@@ -745,7 +745,7 @@ pub fn call(globalObject: *jsc.JSGlobalObject, callframe: *jsc.CallFrame) bun.JS
|
||||
};
|
||||
} 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);
|
||||
|
||||
@@ -11,9 +11,9 @@ const This = @This();
|
||||
// into methods on `bun.FD`, and keeping this namespace to just overall stuff
|
||||
// like `Error`, `Maybe`, `Tag`, and so on.
|
||||
const platform_defs = switch (Environment.os) {
|
||||
.mac => @import("./errno/darwin_errno.zig"),
|
||||
.windows => @import("./errno/windows_errno.zig"),
|
||||
.linux => @import("./errno/linux_errno.zig"),
|
||||
.mac => @import("./errno/darwin_errno.zig"),
|
||||
.wasm => {},
|
||||
};
|
||||
pub const workaround_symbols = @import("./workaround_missing_symbols.zig").current;
|
||||
|
||||
@@ -217,7 +217,7 @@ pub fn msg(this: Error) ?[]const u8 {
|
||||
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)),
|
||||
.message = .empty,
|
||||
};
|
||||
@@ -253,7 +253,7 @@ pub fn toShellSystemError(this: Error) SystemError {
|
||||
/// 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)),
|
||||
.message = .empty,
|
||||
};
|
||||
|
||||
@@ -118,6 +118,7 @@ pub const Address = union(enum) {
|
||||
ctx,
|
||||
client,
|
||||
false,
|
||||
null,
|
||||
));
|
||||
},
|
||||
.host => |h| {
|
||||
@@ -127,6 +128,7 @@ pub const Address = union(enum) {
|
||||
ctx,
|
||||
client,
|
||||
false,
|
||||
null,
|
||||
));
|
||||
},
|
||||
}
|
||||
|
||||
@@ -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) {
|
||||
|
||||
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();
|
||||
}));
|
||||
}));
|
||||
}
|
||||
38
test/js/node/test/parallel/test-net-pipe-with-long-path.js
Normal file
38
test/js/node/test/parallel/test-net-pipe-with-long-path.js
Normal file
@@ -0,0 +1,38 @@
|
||||
'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) => {
|
||||
console.error(error);
|
||||
assert.ok(error.code === 'EINVAL');
|
||||
net.connect(pipePath)
|
||||
.on('error', common.mustCall((error) => {
|
||||
console.error(error);
|
||||
assert.ok(error.code === 'EINVAL');
|
||||
}));
|
||||
});
|
||||
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,7 +6,7 @@ import { request } from "http";
|
||||
import { join } from "path";
|
||||
const tmp_dir = tmpdirSync();
|
||||
|
||||
it("throws ENAMETOOLONG when socket path exceeds platform-specific limit", () => {
|
||||
it("throws ENOENT 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(
|
||||
{
|
||||
@@ -32,7 +32,7 @@ it("throws ENAMETOOLONG when socket path exceeds platform-specific limit", () =>
|
||||
return new Response("hello");
|
||||
},
|
||||
}),
|
||||
).toThrow("too long");
|
||||
).toThrow(/^ENOENT: no such file or directory, listen 'a+'$/);
|
||||
});
|
||||
|
||||
it("throws an error when the directory is not found", () => {
|
||||
|
||||
Reference in New Issue
Block a user