struct sockaddr_storage peer;
} SocketData;
-static JSValue sock_set_timeout( JSContext *ctx, JSValueConst this, JSValueConst val ) {
- SocketData * data = JS_GetOpaque2(ctx, this, socket_cid);
- struct timeval t; double delay;
-
- if (!JS_IsNumber(val)
- || JS_ToFloat64(ctx, &delay, val) || delay < 0) {
- t.tv_sec = 0; t.tv_usec = 0;
- delay = -1;
- } else {
- t.tv_sec = (int) delay;
- t.tv_usec = (int) ((delay - t.tv_sec) * 1000000);
- }
-
- if ( setsockopt(data->fd, SOL_SOCKET, SO_SNDTIMEO, &t, sizeof(t))
- || setsockopt(data->fd, SOL_SOCKET, SO_RCVTIMEO, &t, sizeof(t))
- ) return libc_error(ctx);
-
- data->timeout = delay;
-
- if ( delay == 0
- && fcntl(data->fd, F_SETFL, O_NONBLOCK)
- ) return libc_error(ctx);
- else if ( delay != 0
- && fcntl(data->fd, F_SETFL, 0)
- ) return libc_error(ctx);
+static int sock_set_timeout(SocketData *so, double timeout) {
+ struct timeval t = { .tv_sec = 0, .tv_usec = 0 }; int flags = 0;
+
+ if ( timeout == 0 ) flags = O_NONBLOCK;
+ else if ( timeout > 0 ) {
+ t.tv_sec = (int) timeout;
+ t.tv_usec = (int) ((timeout - t.tv_sec) * 1000000);
+ } else timeout = -1;
+
+ if ( !setsockopt(so->fd, SOL_SOCKET, SO_SNDTIMEO, &t, sizeof(t))
+ && !setsockopt(so->fd, SOL_SOCKET, SO_RCVTIMEO, &t, sizeof(t))
+ && !fcntl(so->fd, F_SETFL, flags)
+ ) {
+ so->timeout = timeout;
+ return 0;
+ } else return 1;
+}
+static JSValue js_sock_set_timeout(
+ JSContext *ctx, JSValueConst this, JSValueConst val
+) {
+ double timeout;
+ SocketData * data = JS_GetOpaque2(ctx, this, socket_cid);
+ if (!JS_IsNumber(val) || JS_ToFloat64(ctx, &timeout, val)) timeout = -1;
- return JS_UNDEFINED;
+ if (! sock_set_timeout(data, timeout) ) return JS_UNDEFINED;
+ else return libc_error(ctx);
}
-static JSValue sock_get_timeout( JSContext *ctx, JSValueConst this ) {
+static JSValue js_sock_get_timeout( JSContext *ctx, JSValueConst this ) {
SocketData * data = JS_GetOpaque2(ctx, this, socket_cid);
if ( data->timeout == -1 ) return JS_UNDEFINED;
else return JS_NewFloat64(ctx, data->timeout);
}
-static JSValue sock_get_fd( JSContext *ctx, JSValueConst this ) {
+static JSValue js_sock_get_fd( JSContext *ctx, JSValueConst this ) {
SocketData * data = JS_GetOpaque2(ctx, this, socket_cid);
return JS_NewInt32(ctx, data->fd);
}
-static JSValue sock_get_family( JSContext *ctx, JSValueConst this ) {
+static JSValue js_sock_get_family( JSContext *ctx, JSValueConst this ) {
SocketData * data = JS_GetOpaque2(ctx, this, socket_cid);
return JS_NewInt32(ctx, data->bind.ss_family);
}
-static JSValue sock_get_type( JSContext *ctx, JSValueConst this ) {
+static JSValue js_sock_get_type( JSContext *ctx, JSValueConst this ) {
SocketData * data = JS_GetOpaque2(ctx, this, socket_cid);
return JS_NewInt32(ctx, data->type);
}
-static JSValue sock_get_connected( JSContext *ctx, JSValueConst this ) {
+static JSValue js_sock_get_connected( JSContext *ctx, JSValueConst this ) {
SocketData * data = JS_GetOpaque2(ctx, this, socket_cid);
return JS_NewBool(ctx, data->connected);
}
-static JSValue sock_accept(
+static JSValue js_sock_accept(
JSContext *ctx, JSValueConst this, int argc, JSValueConst *argv
) {
SocketData * data = JS_GetOpaque2(ctx, this, socket_cid);
memcpy(&(newdata->bind), &(data->bind), sizeof(data->bind));
newdata->connected = 1;
JS_SetOpaque(new, newdata);
- if (data->timeout >= 0)
- (void) sock_set_timeout(ctx, new, JS_NewFloat64(ctx, data->timeout));
- else newdata->timeout = -1;
+ (void) sock_set_timeout(newdata, data->timeout);
return new;
} else {
else return libc_error(ctx);
}
}
-static JSValue sock_send(
+static JSValue js_sock_send(
JSContext *ctx, JSValueConst this, int argc, JSValueConst *argv
) {
SocketData * data = JS_GetOpaque2(ctx, this, socket_cid);
// destination should not be given for SOCK_STREAM sockets
} else to = NULL;
- if (data->timeout == 0) flags |= MSG_DONTWAIT;
-
// Read Argument either as ArrayBuffer or String
if ( (buf = JS_GetArrayBuffer(ctx, &len, argv[0])) ) {
len = sendto(data->fd, buf, len, flags, to, to ? sizeof(*to) : 0);
js_free_rt(rt, buf);
}
-static JSValue sock_recv(
+static JSValue js_sock_recv(
JSContext *ctx, JSValueConst this, int argc, JSValueConst *argv, int str
) {
SocketData * data = JS_GetOpaque2(ctx, this, socket_cid);
- uint8_t *buf; int len; JSValue jbuf; int flags = 0;
+ uint8_t *buf; int len; JSValue jbuf;
socklen_t ps = sizeof(data->peer);
// check current queue size if no valid length was given
) return libc_error(ctx);
if (len <= 0) len = 65535; // if no data is queued, wait for next packet
- if (data->timeout == 0) flags |= MSG_DONTWAIT;
if ( ( buf = js_malloc(ctx, len) )
- && ((len = recvfrom(data->fd, buf, len, flags,
+ && ((len = recvfrom(data->fd, buf, len, 0,
(struct sockaddr *) &(data->peer), &ps)) >= 0)
) {
// resize/clear buffer in case of short read,
}
}
-static JSValue sock_get_addr( JSContext *ctx, JSValueConst this, int magic ) {
+static JSValue js_sock_get_addr( JSContext *ctx, JSValueConst this, int magic ) {
SocketData * data = JS_GetOpaque2(ctx, this, socket_cid);
struct sockaddr_storage * addr = (magic&2) ? &(data->peer) : &(data->bind);
char host[40];
} else return JS_UNDEFINED;
}
-static JSValue sock_close(
+static JSValue js_sock_close(
JSContext *ctx, JSValueConst this, int argc, JSValueConst *argv
) {
SocketData *data = JS_GetOpaque2(ctx, this, socket_cid);
};
static const JSCFunctionListEntry socket_ptype[] = {
- JS_CFUNC_DEF("accept", 0, sock_accept),
- JS_CFUNC_DEF("send", 1, sock_send),
- JS_CFUNC_DEF("close", 0, sock_close),
- JS_CFUNC_MAGIC_DEF("recv", 0, sock_recv, 0),
- JS_CFUNC_MAGIC_DEF("recvString", 0, sock_recv, 1),
- JS_CGETSET_MAGIC_DEF("localName", sock_get_addr, NULL, 0),
- JS_CGETSET_MAGIC_DEF("localPort", sock_get_addr, NULL, 1),
- JS_CGETSET_MAGIC_DEF("peerName", sock_get_addr, NULL, 2),
- JS_CGETSET_MAGIC_DEF("peerPort", sock_get_addr, NULL, 3),
- JS_CGETSET_DEF("timeout", sock_get_timeout, sock_set_timeout),
- JS_CGETSET_DEF("fd", sock_get_fd, NULL),
- JS_CGETSET_DEF("family", sock_get_family, NULL),
- JS_CGETSET_DEF("type", sock_get_type, NULL),
- JS_CGETSET_DEF("connected", sock_get_connected, NULL),
+ JS_CFUNC_DEF("accept", 0, js_sock_accept),
+ JS_CFUNC_DEF("send", 1, js_sock_send),
+ JS_CFUNC_DEF("close", 0, js_sock_close),
+ JS_CFUNC_MAGIC_DEF("recv", 0, js_sock_recv, 0),
+ JS_CFUNC_MAGIC_DEF("recvString", 0, js_sock_recv, 1),
+ JS_CGETSET_MAGIC_DEF("localName", js_sock_get_addr, NULL, 0),
+ JS_CGETSET_MAGIC_DEF("localPort", js_sock_get_addr, NULL, 1),
+ JS_CGETSET_MAGIC_DEF("peerName", js_sock_get_addr, NULL, 2),
+ JS_CGETSET_MAGIC_DEF("peerPort", js_sock_get_addr, NULL, 3),
+ JS_CGETSET_DEF("timeout", js_sock_get_timeout, js_sock_set_timeout),
+ JS_CGETSET_DEF("fd", js_sock_get_fd, NULL),
+ JS_CGETSET_DEF("family", js_sock_get_family, NULL),
+ JS_CGETSET_DEF("type", js_sock_get_type, NULL),
+ JS_CGETSET_DEF("connected", js_sock_get_connected, NULL),
};
static JSClassDef socket_class = {
if ( (so->fd = socket(so->bind.ss_family, type, 0)) >= 0
&& !bind(so->fd, (struct sockaddr *) &(so->bind), sizeof(so->bind))
+ && !sock_set_timeout(so, net_timeout)
&& (type == SOCK_DGRAM || !listen(so->fd, 1))
){
so->type = type;
- so->timeout = -1;
return 0;
} else {
if (so->fd >= 0) close(so->fd);
if (!so) return 1;
if ( (so->fd = socket(so->peer.ss_family, type, 0)) >= 0
+ && !sock_set_timeout(so, net_timeout)
&& !connect(so->fd, (struct sockaddr *) &(so->peer), ps)
&& !getsockname(so->fd, (struct sockaddr *) &(so->bind), &ps)
){
so->type = type;
- so->timeout = -1;
so->connected = 1;
return 0;
} else {
static int net_unix_bind(SocketData *so, const char *path, size_t plen, int con) {
struct sockaddr_un * addr;
- if (!so) return 1;
+ if (!so || plen >= sizeof(addr->sun_path)) return 1;
addr = (struct sockaddr_un *) (con ? &(so->peer) : &(so->bind));
addr->sun_family = AF_UNIX;
- if (plen < sizeof(addr->sun_path)) strncpy(addr->sun_path, path, plen);
+ strncpy(addr->sun_path, path, plen);
+ so->type = SOCK_STREAM;
- if ( (so->fd = socket(AF_UNIX, SOCK_STREAM, 0)) >= 0
- && !( con ? connect(so->fd,(struct sockaddr *) addr ,sizeof(*addr))
- : bind(so->fd,(struct sockaddr *) addr ,sizeof(*addr))
- ) && (con || !listen(so->fd, 1))
+ if ( con
+ && (so->fd = socket(AF_UNIX, so->type, 0)) >= 0
+ && !sock_set_timeout(so, net_timeout)
+ && !connect(so->fd,(struct sockaddr *) addr ,sizeof(*addr))
+ ) {
+ so->connected = 1;
+ return 0;
+ } else if (!con
+ && (so->fd = socket(AF_UNIX, so->type, 0)) >= 0
+ && !bind(so->fd,(struct sockaddr *) addr ,sizeof(*addr))
+ && !sock_set_timeout(so, net_timeout)
+ && !listen(so->fd, 1)
) {
- so->type = SOCK_STREAM;
- so->connected = con;
- so->timeout = -1;
return 0;
} else {
if (so->fd >= 0) close(so->fd);
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_CFUNC_MAGIC_DEF("udpListen", 2, js_net_ip_listen, 0),
- JS_CFUNC_MAGIC_DEF("tcpListen", 2, js_net_ip_listen, 1),
- JS_CFUNC_MAGIC_DEF("udp6Listen", 2, js_net_ip_listen, 2),
- JS_CFUNC_MAGIC_DEF("tcp6Listen", 2, js_net_ip_listen, 3),
+ JS_CFUNC_MAGIC_DEF("udpListen", 2, js_net_ip_listen, 0),
+ JS_CFUNC_MAGIC_DEF("tcpListen", 2, js_net_ip_listen, 1),
+ JS_CFUNC_MAGIC_DEF("udp6Listen", 2, js_net_ip_listen, 2),
+ JS_CFUNC_MAGIC_DEF("tcp6Listen", 2, js_net_ip_listen, 3),
JS_CFUNC_MAGIC_DEF("udpConnect", 2, js_net_ip_connect, 0),
JS_CFUNC_MAGIC_DEF("tcpConnect", 2, js_net_ip_connect, 1),
JS_CFUNC_MAGIC_DEF("udp6Connect", 2, js_net_ip_connect, 2),
JS_CFUNC_MAGIC_DEF("tcp6Connect", 2, js_net_ip_connect, 3),
- JS_CFUNC_MAGIC_DEF("unixListen", 1, js_net_unix_bind, 0),
- JS_CFUNC_MAGIC_DEF("unixConnect", 1, js_net_unix_bind, 1),
+ JS_CFUNC_MAGIC_DEF("unixListen", 1, js_net_unix_bind, 0),
+ JS_CFUNC_MAGIC_DEF("unixConnect", 1, js_net_unix_bind, 1),
// XXX: How does one use a get/set property in a module provided object?
// JS_CGETSET_DEF("timeout", net_get_timeout, net_set_timeout),
JS_CFUNC_DEF("getConnectTimeout", 1, net_get_timeout),
};
-// static const JSCFunctionListEntry net_obj[] = {
-// JS_OBJECT_DEF("net", net_funcs, countof(net_funcs), JS_PROP_CONFIGURABLE)
-// };
-
static int sock_modinit(JSContext *ctx, JSModuleDef *mod ) {
JSValue proto = JS_NewObject(ctx);
if (mod) {
JS_AddModuleExportList(ctx, mod, net_funcs, countof(net_funcs));
- // JS_SetPropertyFunctionList(ctx, global, net_obj, countof(net_obj));
if ( !JS_IsUndefined(os) )
JS_SetPropertyFunctionList(ctx, os, os_socket_funcs,
countof(os_socket_funcs));