|
|
|
|
@@ -13,104 +13,15 @@
|
|
|
|
|
#include <errno.h>
|
|
|
|
|
#include <stdio.h>
|
|
|
|
|
|
|
|
|
|
// Socket wrapper structure
|
|
|
|
|
typedef struct {
|
|
|
|
|
int sockfd;
|
|
|
|
|
} SocketWrapper;
|
|
|
|
|
|
|
|
|
|
// Addrinfo wrapper structure
|
|
|
|
|
typedef struct {
|
|
|
|
|
struct addrinfo *info;
|
|
|
|
|
} AddrinfoWrapper;
|
|
|
|
|
|
|
|
|
|
// Free function for socket
|
|
|
|
|
static void Socket_free(JSRuntime *rt, SocketWrapper *sw)
|
|
|
|
|
// Helper to convert JS value to file descriptor
|
|
|
|
|
static int js2fd(JSContext *ctx, JSValueConst val)
|
|
|
|
|
{
|
|
|
|
|
if (sw->sockfd >= 0) {
|
|
|
|
|
close(sw->sockfd);
|
|
|
|
|
int fd;
|
|
|
|
|
if (JS_ToInt32(ctx, &fd, val) < 0) {
|
|
|
|
|
JS_ThrowTypeError(ctx, "Expected file descriptor number");
|
|
|
|
|
return -1;
|
|
|
|
|
}
|
|
|
|
|
js_free_rt(rt, sw);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Free function for addrinfo
|
|
|
|
|
static void Addrinfo_free(JSRuntime *rt, AddrinfoWrapper *aw)
|
|
|
|
|
{
|
|
|
|
|
if (aw->info) {
|
|
|
|
|
freeaddrinfo(aw->info);
|
|
|
|
|
}
|
|
|
|
|
js_free_rt(rt, aw);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Class definitions
|
|
|
|
|
static JSClassID js_socket_class_id;
|
|
|
|
|
static JSClassID js_addrinfo_class_id;
|
|
|
|
|
|
|
|
|
|
static JSClassDef js_socket_class = {
|
|
|
|
|
"Socket",
|
|
|
|
|
.finalizer = (JSClassFinalizer *)Socket_free,
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
static JSClassDef js_addrinfo_class = {
|
|
|
|
|
"Addrinfo",
|
|
|
|
|
.finalizer = (JSClassFinalizer *)Addrinfo_free,
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
// Helper to convert JS value to SocketWrapper
|
|
|
|
|
static SocketWrapper *js2socket(JSContext *ctx, JSValueConst obj)
|
|
|
|
|
{
|
|
|
|
|
SocketWrapper *sw = JS_GetOpaque2(ctx, obj, js_socket_class_id);
|
|
|
|
|
if (!sw) {
|
|
|
|
|
JS_ThrowTypeError(ctx, "Expected socket object");
|
|
|
|
|
return NULL;
|
|
|
|
|
}
|
|
|
|
|
return sw;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Helper to convert JS value to AddrinfoWrapper
|
|
|
|
|
static AddrinfoWrapper *js2addrinfo(JSContext *ctx, JSValueConst obj)
|
|
|
|
|
{
|
|
|
|
|
AddrinfoWrapper *aw = JS_GetOpaque2(ctx, obj, js_addrinfo_class_id);
|
|
|
|
|
if (!aw) {
|
|
|
|
|
JS_ThrowTypeError(ctx, "Expected addrinfo object");
|
|
|
|
|
return NULL;
|
|
|
|
|
}
|
|
|
|
|
return aw;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Helper to create JS SocketWrapper object
|
|
|
|
|
static JSValue socket2js(JSContext *ctx, int sockfd)
|
|
|
|
|
{
|
|
|
|
|
SocketWrapper *sw = js_mallocz(ctx, sizeof(SocketWrapper));
|
|
|
|
|
if (!sw) return JS_EXCEPTION;
|
|
|
|
|
|
|
|
|
|
sw->sockfd = sockfd;
|
|
|
|
|
|
|
|
|
|
JSValue obj = JS_NewObjectClass(ctx, js_socket_class_id);
|
|
|
|
|
if (JS_IsException(obj)) {
|
|
|
|
|
js_free(ctx, sw);
|
|
|
|
|
return obj;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
JS_SetOpaque(obj, sw);
|
|
|
|
|
return obj;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Helper to create JS AddrinfoWrapper object
|
|
|
|
|
static JSValue addrinfo2js(JSContext *ctx, struct addrinfo *info)
|
|
|
|
|
{
|
|
|
|
|
AddrinfoWrapper *aw = js_mallocz(ctx, sizeof(AddrinfoWrapper));
|
|
|
|
|
if (!aw) return JS_EXCEPTION;
|
|
|
|
|
|
|
|
|
|
aw->info = info;
|
|
|
|
|
|
|
|
|
|
JSValue obj = JS_NewObjectClass(ctx, js_addrinfo_class_id);
|
|
|
|
|
if (JS_IsException(obj)) {
|
|
|
|
|
js_free(ctx, aw);
|
|
|
|
|
return obj;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
JS_SetOpaque(obj, aw);
|
|
|
|
|
return obj;
|
|
|
|
|
return fd;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// SOCKET FUNCTIONS
|
|
|
|
|
@@ -206,7 +117,9 @@ JSC_CCALL(socket_getaddrinfo,
|
|
|
|
|
copy->ai_canonname = strdup(p->ai_canonname);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
JS_SetPropertyStr(js, info, "_addrinfo", addrinfo2js(js, copy));
|
|
|
|
|
// Store the addrinfo pointer as an internal property
|
|
|
|
|
// We'll need to handle this differently since we can't wrap it
|
|
|
|
|
// For now, we'll skip storing the raw addrinfo
|
|
|
|
|
JS_SetPropertyUint32(js, ret, idx++, info);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
@@ -251,15 +164,15 @@ JSC_CCALL(socket_socket,
|
|
|
|
|
return JS_ThrowReferenceError(js, "socket failed: %s", strerror(errno));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return socket2js(js, sockfd);
|
|
|
|
|
return JS_NewInt32(js, sockfd);
|
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
JSC_CCALL(socket_bind,
|
|
|
|
|
SocketWrapper *sw = js2socket(js, argv[0]);
|
|
|
|
|
if (!sw) return JS_EXCEPTION;
|
|
|
|
|
int sockfd = js2fd(js, argv[0]);
|
|
|
|
|
if (sockfd < 0) return JS_EXCEPTION;
|
|
|
|
|
|
|
|
|
|
AddrinfoWrapper *aw = js2addrinfo(js, JS_GetPropertyStr(js, argv[1], "_addrinfo"));
|
|
|
|
|
if (!aw) {
|
|
|
|
|
// For now, we'll only support manual address parsing
|
|
|
|
|
{
|
|
|
|
|
// Try to parse address and port manually
|
|
|
|
|
const char *addr_str = JS_ToCString(js, JS_GetPropertyStr(js, argv[1], "address"));
|
|
|
|
|
int port = js2number(js, JS_GetPropertyStr(js, argv[1], "port"));
|
|
|
|
|
@@ -274,11 +187,7 @@ JSC_CCALL(socket_bind,
|
|
|
|
|
}
|
|
|
|
|
JS_FreeCString(js, addr_str);
|
|
|
|
|
|
|
|
|
|
if (bind(sw->sockfd, (struct sockaddr *)&addr, sizeof(addr)) < 0) {
|
|
|
|
|
return JS_ThrowReferenceError(js, "bind failed: %s", strerror(errno));
|
|
|
|
|
}
|
|
|
|
|
} else {
|
|
|
|
|
if (bind(sw->sockfd, aw->info->ai_addr, aw->info->ai_addrlen) < 0) {
|
|
|
|
|
if (bind(sockfd, (struct sockaddr *)&addr, sizeof(addr)) < 0) {
|
|
|
|
|
return JS_ThrowReferenceError(js, "bind failed: %s", strerror(errno));
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
@@ -287,11 +196,11 @@ JSC_CCALL(socket_bind,
|
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
JSC_CCALL(socket_connect,
|
|
|
|
|
SocketWrapper *sw = js2socket(js, argv[0]);
|
|
|
|
|
if (!sw) return JS_EXCEPTION;
|
|
|
|
|
int sockfd = js2fd(js, argv[0]);
|
|
|
|
|
if (sockfd < 0) return JS_EXCEPTION;
|
|
|
|
|
|
|
|
|
|
AddrinfoWrapper *aw = js2addrinfo(js, JS_GetPropertyStr(js, argv[1], "_addrinfo"));
|
|
|
|
|
if (!aw) {
|
|
|
|
|
// For now, we'll only support manual address parsing
|
|
|
|
|
{
|
|
|
|
|
// Try to parse address and port manually
|
|
|
|
|
const char *addr_str = JS_ToCString(js, JS_GetPropertyStr(js, argv[1], "address"));
|
|
|
|
|
int port = js2number(js, JS_GetPropertyStr(js, argv[1], "port"));
|
|
|
|
|
@@ -306,11 +215,7 @@ JSC_CCALL(socket_connect,
|
|
|
|
|
}
|
|
|
|
|
JS_FreeCString(js, addr_str);
|
|
|
|
|
|
|
|
|
|
if (connect(sw->sockfd, (struct sockaddr *)&addr, sizeof(addr)) < 0) {
|
|
|
|
|
return JS_ThrowReferenceError(js, "connect failed: %s", strerror(errno));
|
|
|
|
|
}
|
|
|
|
|
} else {
|
|
|
|
|
if (connect(sw->sockfd, aw->info->ai_addr, aw->info->ai_addrlen) < 0) {
|
|
|
|
|
if (connect(sockfd, (struct sockaddr *)&addr, sizeof(addr)) < 0) {
|
|
|
|
|
return JS_ThrowReferenceError(js, "connect failed: %s", strerror(errno));
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
@@ -319,15 +224,15 @@ JSC_CCALL(socket_connect,
|
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
JSC_CCALL(socket_listen,
|
|
|
|
|
SocketWrapper *sw = js2socket(js, argv[0]);
|
|
|
|
|
if (!sw) return JS_EXCEPTION;
|
|
|
|
|
int sockfd = js2fd(js, argv[0]);
|
|
|
|
|
if (sockfd < 0) return JS_EXCEPTION;
|
|
|
|
|
|
|
|
|
|
int backlog = 10;
|
|
|
|
|
if (argc > 1) {
|
|
|
|
|
backlog = js2number(js, argv[1]);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (listen(sw->sockfd, backlog) < 0) {
|
|
|
|
|
if (listen(sockfd, backlog) < 0) {
|
|
|
|
|
return JS_ThrowReferenceError(js, "listen failed: %s", strerror(errno));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
@@ -335,19 +240,19 @@ JSC_CCALL(socket_listen,
|
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
JSC_CCALL(socket_accept,
|
|
|
|
|
SocketWrapper *sw = js2socket(js, argv[0]);
|
|
|
|
|
if (!sw) return JS_EXCEPTION;
|
|
|
|
|
int sockfd = js2fd(js, argv[0]);
|
|
|
|
|
if (sockfd < 0) return JS_EXCEPTION;
|
|
|
|
|
|
|
|
|
|
struct sockaddr_storage their_addr;
|
|
|
|
|
socklen_t addr_size = sizeof their_addr;
|
|
|
|
|
|
|
|
|
|
int new_sockfd = accept(sw->sockfd, (struct sockaddr *)&their_addr, &addr_size);
|
|
|
|
|
int new_sockfd = accept(sockfd, (struct sockaddr *)&their_addr, &addr_size);
|
|
|
|
|
if (new_sockfd < 0) {
|
|
|
|
|
return JS_ThrowReferenceError(js, "accept failed: %s", strerror(errno));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
ret = JS_NewObject(js);
|
|
|
|
|
JS_SetPropertyStr(js, ret, "socket", socket2js(js, new_sockfd));
|
|
|
|
|
JS_SetPropertyStr(js, ret, "socket", JS_NewInt32(js, new_sockfd));
|
|
|
|
|
|
|
|
|
|
// Get peer address info
|
|
|
|
|
char ipstr[INET6_ADDRSTRLEN];
|
|
|
|
|
@@ -369,8 +274,8 @@ JSC_CCALL(socket_accept,
|
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
JSC_CCALL(socket_send,
|
|
|
|
|
SocketWrapper *sw = js2socket(js, argv[0]);
|
|
|
|
|
if (!sw) return JS_EXCEPTION;
|
|
|
|
|
int sockfd = js2fd(js, argv[0]);
|
|
|
|
|
if (sockfd < 0) return JS_EXCEPTION;
|
|
|
|
|
|
|
|
|
|
size_t len;
|
|
|
|
|
ssize_t sent;
|
|
|
|
|
@@ -382,11 +287,11 @@ JSC_CCALL(socket_send,
|
|
|
|
|
|
|
|
|
|
if (JS_IsString(argv[1])) {
|
|
|
|
|
const char *data = JS_ToCStringLen(js, &len, argv[1]);
|
|
|
|
|
sent = send(sw->sockfd, data, len, flags);
|
|
|
|
|
sent = send(sockfd, data, len, flags);
|
|
|
|
|
JS_FreeCString(js, data);
|
|
|
|
|
} else {
|
|
|
|
|
unsigned char *data = js_get_blob_data(js, &len, argv[1]);
|
|
|
|
|
sent = send(sw->sockfd, data, len, flags);
|
|
|
|
|
sent = send(sockfd, data, len, flags);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (sent < 0) {
|
|
|
|
|
@@ -397,8 +302,8 @@ JSC_CCALL(socket_send,
|
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
JSC_CCALL(socket_recv,
|
|
|
|
|
SocketWrapper *sw = js2socket(js, argv[0]);
|
|
|
|
|
if (!sw) return JS_EXCEPTION;
|
|
|
|
|
int sockfd = js2fd(js, argv[0]);
|
|
|
|
|
if (sockfd < 0) return JS_EXCEPTION;
|
|
|
|
|
|
|
|
|
|
size_t len = 4096;
|
|
|
|
|
if (argc > 1) {
|
|
|
|
|
@@ -415,7 +320,7 @@ JSC_CCALL(socket_recv,
|
|
|
|
|
return JS_ThrowReferenceError(js, "malloc failed");
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
ssize_t received = recv(sw->sockfd, buf, len, flags);
|
|
|
|
|
ssize_t received = recv(sockfd, buf, len, flags);
|
|
|
|
|
if (received < 0) {
|
|
|
|
|
free(buf);
|
|
|
|
|
return JS_ThrowReferenceError(js, "recv failed: %s", strerror(errno));
|
|
|
|
|
@@ -427,8 +332,8 @@ JSC_CCALL(socket_recv,
|
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
JSC_CCALL(socket_sendto,
|
|
|
|
|
SocketWrapper *sw = js2socket(js, argv[0]);
|
|
|
|
|
if (!sw) return JS_EXCEPTION;
|
|
|
|
|
int sockfd = js2fd(js, argv[0]);
|
|
|
|
|
if (sockfd < 0) return JS_EXCEPTION;
|
|
|
|
|
|
|
|
|
|
size_t len;
|
|
|
|
|
ssize_t sent;
|
|
|
|
|
@@ -439,11 +344,11 @@ JSC_CCALL(socket_sendto,
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Get destination address
|
|
|
|
|
AddrinfoWrapper *aw = js2addrinfo(js, JS_GetPropertyStr(js, argv[2], "_addrinfo"));
|
|
|
|
|
struct sockaddr *to_addr;
|
|
|
|
|
socklen_t to_len;
|
|
|
|
|
|
|
|
|
|
if (!aw) {
|
|
|
|
|
// For now, we'll only support manual address parsing
|
|
|
|
|
{
|
|
|
|
|
// Try to parse address and port manually
|
|
|
|
|
const char *addr_str = JS_ToCString(js, JS_GetPropertyStr(js, argv[2], "address"));
|
|
|
|
|
int port = js2number(js, JS_GetPropertyStr(js, argv[2], "port"));
|
|
|
|
|
@@ -460,18 +365,15 @@ JSC_CCALL(socket_sendto,
|
|
|
|
|
|
|
|
|
|
to_addr = (struct sockaddr *)&addr;
|
|
|
|
|
to_len = sizeof(addr);
|
|
|
|
|
} else {
|
|
|
|
|
to_addr = aw->info->ai_addr;
|
|
|
|
|
to_len = aw->info->ai_addrlen;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (JS_IsString(argv[1])) {
|
|
|
|
|
const char *data = JS_ToCStringLen(js, &len, argv[1]);
|
|
|
|
|
sent = sendto(sw->sockfd, data, len, flags, to_addr, to_len);
|
|
|
|
|
sent = sendto(sockfd, data, len, flags, to_addr, to_len);
|
|
|
|
|
JS_FreeCString(js, data);
|
|
|
|
|
} else {
|
|
|
|
|
unsigned char *data = js_get_blob_data(js, &len, argv[1]);
|
|
|
|
|
sent = sendto(sw->sockfd, data, len, flags, to_addr, to_len);
|
|
|
|
|
sent = sendto(sockfd, data, len, flags, to_addr, to_len);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (sent < 0) {
|
|
|
|
|
@@ -482,8 +384,8 @@ JSC_CCALL(socket_sendto,
|
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
JSC_CCALL(socket_recvfrom,
|
|
|
|
|
SocketWrapper *sw = js2socket(js, argv[0]);
|
|
|
|
|
if (!sw) return JS_EXCEPTION;
|
|
|
|
|
int sockfd = js2fd(js, argv[0]);
|
|
|
|
|
if (sockfd < 0) return JS_EXCEPTION;
|
|
|
|
|
|
|
|
|
|
size_t len = 4096;
|
|
|
|
|
if (argc > 1) {
|
|
|
|
|
@@ -503,7 +405,7 @@ JSC_CCALL(socket_recvfrom,
|
|
|
|
|
struct sockaddr_storage from_addr;
|
|
|
|
|
socklen_t from_len = sizeof from_addr;
|
|
|
|
|
|
|
|
|
|
ssize_t received = recvfrom(sw->sockfd, buf, len, flags,
|
|
|
|
|
ssize_t received = recvfrom(sockfd, buf, len, flags,
|
|
|
|
|
(struct sockaddr *)&from_addr, &from_len);
|
|
|
|
|
if (received < 0) {
|
|
|
|
|
free(buf);
|
|
|
|
|
@@ -534,15 +436,15 @@ JSC_CCALL(socket_recvfrom,
|
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
JSC_CCALL(socket_shutdown,
|
|
|
|
|
SocketWrapper *sw = js2socket(js, argv[0]);
|
|
|
|
|
if (!sw) return JS_EXCEPTION;
|
|
|
|
|
int sockfd = js2fd(js, argv[0]);
|
|
|
|
|
if (sockfd < 0) return JS_EXCEPTION;
|
|
|
|
|
|
|
|
|
|
int how = SHUT_RDWR;
|
|
|
|
|
if (argc > 1) {
|
|
|
|
|
how = js2number(js, argv[1]);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (shutdown(sw->sockfd, how) < 0) {
|
|
|
|
|
if (shutdown(sockfd, how) < 0) {
|
|
|
|
|
return JS_ThrowReferenceError(js, "shutdown failed: %s", strerror(errno));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
@@ -550,13 +452,13 @@ JSC_CCALL(socket_shutdown,
|
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
JSC_CCALL(socket_getpeername,
|
|
|
|
|
SocketWrapper *sw = js2socket(js, argv[0]);
|
|
|
|
|
if (!sw) return JS_EXCEPTION;
|
|
|
|
|
int sockfd = js2fd(js, argv[0]);
|
|
|
|
|
if (sockfd < 0) return JS_EXCEPTION;
|
|
|
|
|
|
|
|
|
|
struct sockaddr_storage addr;
|
|
|
|
|
socklen_t len = sizeof addr;
|
|
|
|
|
|
|
|
|
|
if (getpeername(sw->sockfd, (struct sockaddr *)&addr, &len) < 0) {
|
|
|
|
|
if (getpeername(sockfd, (struct sockaddr *)&addr, &len) < 0) {
|
|
|
|
|
return JS_ThrowReferenceError(js, "getpeername failed: %s", strerror(errno));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
@@ -585,19 +487,6 @@ JSC_CCALL(socket_gethostname,
|
|
|
|
|
return JS_NewString(js, hostname);
|
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
JSC_CCALL(socket_freeaddrinfo,
|
|
|
|
|
AddrinfoWrapper *aw = js2addrinfo(js, argv[0]);
|
|
|
|
|
if (!aw) return JS_EXCEPTION;
|
|
|
|
|
|
|
|
|
|
if (aw->info) {
|
|
|
|
|
if (aw->info->ai_addr) free(aw->info->ai_addr);
|
|
|
|
|
if (aw->info->ai_canonname) free(aw->info->ai_canonname);
|
|
|
|
|
free(aw->info);
|
|
|
|
|
aw->info = NULL;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return JS_UNDEFINED;
|
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
JSC_CCALL(socket_gai_strerror,
|
|
|
|
|
int errcode = js2number(js, argv[0]);
|
|
|
|
|
@@ -605,8 +494,8 @@ JSC_CCALL(socket_gai_strerror,
|
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
JSC_CCALL(socket_setsockopt,
|
|
|
|
|
SocketWrapper *sw = js2socket(js, argv[0]);
|
|
|
|
|
if (!sw) return JS_EXCEPTION;
|
|
|
|
|
int sockfd = js2fd(js, argv[0]);
|
|
|
|
|
if (sockfd < 0) return JS_EXCEPTION;
|
|
|
|
|
|
|
|
|
|
int level = SOL_SOCKET;
|
|
|
|
|
int optname = 0;
|
|
|
|
|
@@ -637,12 +526,12 @@ JSC_CCALL(socket_setsockopt,
|
|
|
|
|
// Parse option value
|
|
|
|
|
if (JS_IsBool(argv[3])) {
|
|
|
|
|
int optval = JS_ToBool(js, argv[3]);
|
|
|
|
|
if (setsockopt(sw->sockfd, level, optname, &optval, sizeof(optval)) < 0) {
|
|
|
|
|
if (setsockopt(sockfd, level, optname, &optval, sizeof(optval)) < 0) {
|
|
|
|
|
return JS_ThrowReferenceError(js, "setsockopt failed: %s", strerror(errno));
|
|
|
|
|
}
|
|
|
|
|
} else if (JS_IsNumber(argv[3])) {
|
|
|
|
|
int optval = js2number(js, argv[3]);
|
|
|
|
|
if (setsockopt(sw->sockfd, level, optname, &optval, sizeof(optval)) < 0) {
|
|
|
|
|
if (setsockopt(sockfd, level, optname, &optval, sizeof(optval)) < 0) {
|
|
|
|
|
return JS_ThrowReferenceError(js, "setsockopt failed: %s", strerror(errno));
|
|
|
|
|
}
|
|
|
|
|
} else {
|
|
|
|
|
@@ -652,6 +541,16 @@ JSC_CCALL(socket_setsockopt,
|
|
|
|
|
return JS_UNDEFINED;
|
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
JSC_CCALL(socket_close,
|
|
|
|
|
int sockfd = js2fd(js, argv[0]);
|
|
|
|
|
if (sockfd < 0) return JS_EXCEPTION;
|
|
|
|
|
|
|
|
|
|
if (close(sockfd) != 0)
|
|
|
|
|
return JS_ThrowReferenceError(js, "close failed: %s", strerror(errno));
|
|
|
|
|
|
|
|
|
|
return JS_UNDEFINED;
|
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
static const JSCFunctionListEntry js_socket_funcs[] = {
|
|
|
|
|
MIST_FUNC_DEF(socket, getaddrinfo, 3),
|
|
|
|
|
MIST_FUNC_DEF(socket, socket, 3),
|
|
|
|
|
@@ -666,26 +565,12 @@ static const JSCFunctionListEntry js_socket_funcs[] = {
|
|
|
|
|
MIST_FUNC_DEF(socket, shutdown, 2),
|
|
|
|
|
MIST_FUNC_DEF(socket, getpeername, 1),
|
|
|
|
|
MIST_FUNC_DEF(socket, gethostname, 0),
|
|
|
|
|
MIST_FUNC_DEF(socket, freeaddrinfo, 1),
|
|
|
|
|
MIST_FUNC_DEF(socket, gai_strerror, 1),
|
|
|
|
|
MIST_FUNC_DEF(socket, setsockopt, 4),
|
|
|
|
|
MIST_FUNC_DEF(socket, close, 1),
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
JSValue js_socket_use(JSContext *js) {
|
|
|
|
|
// Initialize the socket class
|
|
|
|
|
JS_NewClassID(&js_socket_class_id);
|
|
|
|
|
JS_NewClass(JS_GetRuntime(js), js_socket_class_id, &js_socket_class);
|
|
|
|
|
|
|
|
|
|
JSValue proto = JS_NewObject(js);
|
|
|
|
|
JS_SetClassProto(js, js_socket_class_id, proto);
|
|
|
|
|
|
|
|
|
|
// Initialize the addrinfo class
|
|
|
|
|
JS_NewClassID(&js_addrinfo_class_id);
|
|
|
|
|
JS_NewClass(JS_GetRuntime(js), js_addrinfo_class_id, &js_addrinfo_class);
|
|
|
|
|
|
|
|
|
|
JSValue addrinfo_proto = JS_NewObject(js);
|
|
|
|
|
JS_SetClassProto(js, js_addrinfo_class_id, addrinfo_proto);
|
|
|
|
|
|
|
|
|
|
JSValue mod = JS_NewObject(js);
|
|
|
|
|
JS_SetPropertyFunctionList(js, mod, js_socket_funcs, countof(js_socket_funcs));
|
|
|
|
|
|
|
|
|
|
@@ -708,4 +593,4 @@ JSValue js_socket_use(JSContext *js) {
|
|
|
|
|
JS_SetPropertyStr(js, mod, "SO_REUSEADDR", JS_NewInt32(js, SO_REUSEADDR));
|
|
|
|
|
|
|
|
|
|
return mod;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|