From dd33ad1835481f59204d04938240bf4f7a380d07 Mon Sep 17 00:00:00 2001 From: =?utf8?q?Paul=20H=C3=A4nsch?= Date: Wed, 11 Mar 2026 04:10:22 +0100 Subject: [PATCH] overall testing and cleanup, optimisations in listener functions --- socket.c | 65 +++++++++++++++++++++----------------------------------- 1 file changed, 24 insertions(+), 41 deletions(-) diff --git a/socket.c b/socket.c index 9c3d58e..12ea884 100644 --- a/socket.c +++ b/socket.c @@ -12,6 +12,11 @@ #define countof(x) ( sizeof(x) / sizeof(x[0]) ) #define libc_error(ctx) ( JS_ThrowInternalError(ctx, "%s", strerror(errno)) ) +// use struct addrinfo in socket functions +#define ai_socket(a) ( socket( (a)->ai_family, (a)->ai_socktype, (a)->ai_protocol ) ) +#define ai_bind(s, a) ( bind((s), (a)->ai_addr, (a)->ai_addrlen) ) +#define ai_connect(s, a) ( connect((s), (a)->ai_addr, (a)->ai_addrlen) ) + static JSValue js_os_socket( JSContext *ctx, JSValueConst this, int argc, JSValueConst *argv) { int family, type, protocol, fd; @@ -145,12 +150,10 @@ static JSValue sock_send( JSContext *ctx, JSValueConst this, int argc, JSValueC SocketData * data = JS_GetOpaque2(ctx, this, socket_cid); uint8_t *buf; size_t len; - if ( ! data->peer.sa_family ) { - return JS_ThrowInternalError(ctx, "Socket not connected"); - } else if ( (buf = JS_GetArrayBuffer(ctx, &len, argv[0])) ) { - len = send(data->fd, buf, len, 0); + if ( (buf = JS_GetArrayBuffer(ctx, &len, argv[0])) ) { + len = send(data->fd, buf, len, MSG_NOSIGNAL); } else if ( (buf = (uint8_t*) JS_ToCStringLen(ctx, &len, argv[0])) ) { - len = send(data->fd, buf, len, 0); + len = send(data->fd, buf, len, MSG_NOSIGNAL); JS_FreeCString(ctx, (char *) buf); } else return JS_ThrowTypeError(ctx, "expected ArrayBuffer or String" @@ -164,6 +167,7 @@ static JSValue sock_recv( JSContext *ctx, JSValueConst this, int argc, JSValueC SocketData * data = JS_GetOpaque2(ctx, this, socket_cid); uint8_t *buf; int len; JSValue jbuf; + // FIXME: how portable is ioctl/FIONREAD ? if ( (JS_ToInt32(ctx, &len, argv[0]) || len <= 0) && ioctl(data->fd, FIONREAD, &len) ) return libc_error(ctx); @@ -209,35 +213,13 @@ static JSClassDef socket_class = { "Socket", .finalizer = sock_destroy }; - -static int ai_socket(struct addrinfo *address) { - return socket(address->ai_family, - address->ai_socktype, - address->ai_protocol - ); -} - -static int ai_bind(int sock, struct addrinfo *address) { - return bind(sock, - address->ai_addr, - address->ai_addrlen - ); -} - -static int ai_connect(int sock, struct addrinfo *address) { - return connect(sock, - address->ai_addr, - address->ai_addrlen - ); -} - -static JSValue udp_listen( JSContext *ctx, JSValueConst this, int argc, JSValueConst *argv) { - return JS_UNDEFINED; -} -static JSValue tcp_listen( JSContext *ctx, JSValueConst this, int argc, JSValueConst *argv, int family) { - struct addrinfo hints = { .ai_family = family, .ai_socktype = SOCK_STREAM }; - struct addrinfo * self; - const char *host, *port; +static JSValue ip_listen( JSContext *ctx, JSValueConst this, int argc, JSValueConst *argv, int magic) { + struct addrinfo hints = { + .ai_family = (magic&2) ? AF_INET6 : AF_INET, + .ai_socktype = (magic&1) ? SOCK_STREAM : SOCK_DGRAM, + }; + struct addrinfo * self = NULL; + const char *host, *port; int gai_err; SocketData *data = js_mallocz(ctx, sizeof(*data)); JSValue new = JS_NewObjectClass(ctx, socket_cid); @@ -245,10 +227,10 @@ static JSValue tcp_listen( JSContext *ctx, JSValueConst this, int argc, JSValueC port = JS_ToCString(ctx, argv[1]); if ( data && (data->fd = -1) - && !getaddrinfo( host, port, &hints, &self) + && !(gai_err = getaddrinfo( host, port, &hints, &self)) && (data->fd = ai_socket(self)) >= 0 && !ai_bind(data->fd, self) - && !listen(data->fd, 1) + && ( hints.ai_socktype == SOCK_DGRAM || !listen(data->fd, 1)) ) { memcpy(&(data->bind), self->ai_addr, sizeof(struct sockaddr)); JS_SetOpaque(new, data); @@ -256,7 +238,8 @@ static JSValue tcp_listen( JSContext *ctx, JSValueConst this, int argc, JSValueC JS_FreeValue(ctx, new); if (data->fd >= 0) close(data->fd); js_free(ctx, data); - new = libc_error(ctx); + if (!gai_err) new = libc_error(ctx); + else new = JS_ThrowInternalError(ctx, "%s", gai_strerror(gai_err)); } freeaddrinfo(self); JS_FreeCString(ctx, host); JS_FreeCString(ctx, port); @@ -283,10 +266,10 @@ static const JSCFunctionListEntry net_funcs[] = { JS_PROP_INT32_DEF("AF_INET6", AF_INET6, JS_PROP_CONFIGURABLE), JS_PROP_INT32_DEF("SOCK_STREAM", SOCK_STREAM, JS_PROP_CONFIGURABLE), JS_PROP_INT32_DEF("SOCK_DGRAM", SOCK_DGRAM, JS_PROP_CONFIGURABLE), - JS_PROP_INT32_DEF("SOCK_NONBLOCK", SOCK_NONBLOCK, JS_PROP_CONFIGURABLE), - JS_CFUNC_DEF("udpListen", 2, udp_listen), - JS_CFUNC_MAGIC_DEF("tcpListen", 2, tcp_listen, AF_INET), - JS_CFUNC_MAGIC_DEF("tcp6Listen", 2, tcp_listen, AF_INET6), + JS_CFUNC_MAGIC_DEF("udpListen", 2, ip_listen, 0), + JS_CFUNC_MAGIC_DEF("tcpListen", 2, ip_listen, 1), + JS_CFUNC_MAGIC_DEF("udp6Listen", 2, ip_listen, 2), + JS_CFUNC_MAGIC_DEF("tcp6Listen", 2, ip_listen, 3), JS_CFUNC_DEF("unixListen", 1, unix_listen), JS_CFUNC_DEF("udpConnect", 2, udp_connect), JS_CFUNC_DEF("tcpConnect", 2, tcp_connect), -- 2.39.5