return JS_NewInt32(ctx, fork());
}
-static JSValue js_os_socket(
- JSContext *ctx, JSValueConst this, int argc, JSValueConst *argv
-) {
- int family, type, protocol, fd;
-
- if ( argc >= 3
- && ! JS_ToInt32(ctx, &family, argv[0])
- && ! JS_ToInt32(ctx, &type, argv[1])
- && ! JS_ToInt32(ctx, &protocol, argv[2])
- && ( fd = socket(family, type, protocol))
- ) {
- return JS_NewInt32(ctx, fd);
- } else {
- return JS_EXCEPTION;
- }
-}
-
-static JSValue js_os_bind(
- JSContext *ctx, JSValueConst this, int argc, JSValueConst *argv, int con
-) {
- struct addrinfo *addr, *waddr;
- struct sockaddr_un addr_un = { .sun_family = AF_UNIX };
- int fd, b = -1; const char *host, *port, *path;
-
- if ( argc < 2 ) return JS_EXCEPTION;
- if ( JS_ToInt32(ctx, &fd, argv[0]) ) return JS_EXCEPTION;
-
- if ( argc == 2 ) {
- path = JS_ToCString(ctx, argv[1]);
- if (strlen(path) < sizeof(addr_un.sun_path)) {
- strcpy((char *) &(addr_un.sun_path), path);
- if (!con) b = bind(fd, (struct sockaddr *) &addr_un, sizeof(addr_un));
- else b = connect(fd, (struct sockaddr *) &addr_un, sizeof(addr_un));
- }
- JS_FreeCString(ctx, path);
- if (b) return libc_error(ctx); else return JS_UNDEFINED;
-
- } else { // argc >= 3
- host = JS_ToCString(ctx, argv[1]);
- port = JS_ToCString(ctx, argv[2]);
- if (! getaddrinfo(host, port, NULL, &addr))
- waddr = addr;
- JS_FreeCString(ctx, host); JS_FreeCString(ctx, port);
-
- while (waddr) {
- if (!con) b = bind(fd, addr->ai_addr, addr->ai_addrlen);
- else b = connect(fd, addr->ai_addr, addr->ai_addrlen);
- if (!b) break;
- waddr = waddr->ai_next;
- }
- freeaddrinfo(addr);
- if (b) return libc_error(ctx); else return JS_UNDEFINED;
- }
-}
-
-static JSValue js_os_listen(
- JSContext *ctx, JSValueConst this, int argc, JSValueConst *argv
-) {
- int fd, backlog = 1;
-
- if (argc < 1 ) return JS_EXCEPTION;
- if ( JS_ToInt32(ctx, &fd, argv[0]) )
- return JS_EXCEPTION;
- if ( argc >= 2 && JS_ToInt32(ctx, &backlog, argv[1]) )
- return JS_EXCEPTION;
-
- if (! listen(fd, backlog)) return JS_UNDEFINED;
- else return libc_error(ctx);
-}
-
-static JSValue js_os_accept(
- JSContext *ctx, JSValueConst this, int argc, JSValueConst *argv
-) {
- struct sockaddr peer; socklen_t ps = sizeof(struct sockaddr);
- char host[40], port[6];
- int fd, new;
-
- if ( argc < 1 ) return JS_EXCEPTION;
- if ( JS_ToInt32(ctx, &fd, argv[0]) ) return JS_EXCEPTION;
-
- // FIXME: use numeric port number (int instead of string)
- if ( argc >= 2 ) {
- if ((new = accept(fd, &peer, &ps)) != -1) {
- JS_SetPropertyStr(ctx, argv[1], "protocol", JS_NewInt32(ctx, peer.sa_family));
- if ( peer.sa_family != AF_UNIX ) {
- getnameinfo(&peer, ps, host, 40, port, 6, NI_NUMERICHOST | NI_NUMERICSERV);
- JS_SetPropertyStr(ctx, argv[1], "host", JS_NewString(ctx, host));
- JS_SetPropertyStr(ctx, argv[1], "port", JS_NewString(ctx, port));
- }
- }
- } else {
- new = accept(fd, NULL, 0);
- }
- if (new != -1)
- return JS_NewInt32(ctx, new);
- else return JS_EXCEPTION;
-}
-
-static const JSCFunctionListEntry os_socket_funcs[] = {
- JS_CFUNC_DEF("socket", 3, js_os_socket),
- JS_CFUNC_DEF("listen", 1, js_os_listen),
- JS_CFUNC_DEF("accept", 1, js_os_accept),
- JS_CFUNC_DEF("fork", 0, js_os_fork),
- JS_CFUNC_MAGIC_DEF("bind", 2, js_os_bind, 0),
- JS_CFUNC_MAGIC_DEF("connect", 2, js_os_bind, 1),
- // JS_CFUNC_DEF("send", 2, js_os_send), // would be same as os.write
- // JS_CFUNC_DEF("recv", 2, js_os_recv), // would be same as os.read
- // JS_CFUNC_DEF("close", 1, js_os_close), // would be same as os.close
-};
-
static JSClassID socket_cid;
static double net_timeout = -1;
} else return 1;
}
+static int net_addrinfo(
+ int family, int type, const char *host, const char *port,
+ struct sockaddr_storage * addr
+) {
+ struct addrinfo hints = { .ai_family = family, .ai_socktype = type };
+ struct addrinfo * info = NULL; int gai_error = 0;
+
+ if (!(gai_error = getaddrinfo( host, port, &hints, &info ))) {
+ memcpy(addr, info->ai_addr, info->ai_addrlen);
+ }
+ freeaddrinfo(info);
+ return gai_error;
+}
+
+static int net_ip_listen(SocketData *so, int type) {
+ if (!so) return 1;
+
+ 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;
+ return 0;
+ } else {
+ if (so->fd >= 0) close(so->fd);
+ return 1;
+ }
+}
+
static JSValue js_sock_set_timeout(
JSContext *ctx, JSValueConst this, JSValueConst val
) {
int magic;
};
-
static JSValue js_sock_accept(
JSContext *ctx, JSValueConst this, int argc, JSValueConst *argv
) {
JSValue new = JS_NewObjectClass(ctx, socket_cid);
socklen_t ps = sizeof(data->bind);
- if ( newdata
- && ( newdata->fd =
- accept( data->fd, (struct sockaddr *) &(newdata->peer), &ps )
- ) >= 0
+ if ( newdata && ( newdata->fd =
+ accept( data->fd, (struct sockaddr *) &(newdata->peer), &ps )
+ ) >= 0
) {
memcpy(&(newdata->bind), &(data->bind), sizeof(data->bind));
newdata->connected = 1;
) {
SocketData * data = JS_GetOpaque2(ctx, this, socket_cid);
// XXX: how portable is MSG_NOSIGNAL ? (POSIX.1-2008)
- uint8_t *buf; size_t len; int flags = MSG_NOSIGNAL;
- const char *host, *port; int gai_err;
- struct addrinfo hints = { .ai_family = data->bind.ss_family, .ai_socktype = data->type };
- struct addrinfo * dest; struct sockaddr * to;
+ uint8_t *buf; size_t len = 0; int flags = MSG_NOSIGNAL;
+ const char *host, *port; int gai_err = 0;
+ struct sockaddr * to;
// destHost and destPort may be given for UDP sockets
if (data->type == SOCK_DGRAM && argc >= 3) {
host = JS_ToCString(ctx, argv[1]);
port = JS_ToCString(ctx, argv[2]);
- if (! (gai_err = getaddrinfo(host, port, &hints, &dest)))
- memcpy(&(data->peer), dest->ai_addr, dest->ai_addrlen);
+ gai_err = net_addrinfo(
+ data->bind.ss_family, data->type, host, port, &(data->peer)
+ );
JS_FreeCString(ctx, host); JS_FreeCString(ctx, port);
- freeaddrinfo(dest);
if (gai_err) return libc_error(ctx);
to = (struct sockaddr *) &(data->peer);
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;
+ uint8_t *buf; int len = 0; JSValue jbuf;
socklen_t ps = sizeof(data->peer);
// check current queue size if no valid length was given
"Socket", .finalizer = sock_destroy
};
-static int net_addrinfo(
- int family, int type, const char *host, const char *port,
- struct sockaddr_storage * addr
-) {
- struct addrinfo hints = { .ai_family = family, .ai_socktype = type };
- struct addrinfo * info;
- int gai_error;
-
- if (!(gai_error = getaddrinfo( host, port, &hints, &info ))) {
- memcpy(addr, info->ai_addr, info->ai_addrlen);
- }
- freeaddrinfo(info);
- return gai_error;
-}
-
-static int net_ip_listen(SocketData *so, int type) {
- if (!so) return 1;
-
- 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;
- return 0;
- } else {
- if (so->fd >= 0) close(so->fd);
- return 1;
- }
-}
-
static JSValue js_net_ip_listen(
JSContext *ctx, JSValueConst this, int argc, JSValueConst *argv, int magic
) {
int family = (magic&2) ? AF_INET6 : AF_INET;
int type = (magic&1) ? SOCK_STREAM : SOCK_DGRAM;
- const char *host, *port; int gai_err;
+ const char *host, *port; int gai_err = 0;
SocketData *data = js_mallocz(ctx, sizeof(*data));
JSValue new = JS_NewObjectClass(ctx, socket_cid);
) {
int family = (magic&2) ? AF_INET6 : AF_INET;
int type = (magic&1) ? SOCK_STREAM : SOCK_DGRAM;
- const char *host, *port; int gai_err;
+ const char *host, *port; int gai_err = 0;
SocketData *data = js_mallocz(ctx, sizeof(*data));
JSValue new = JS_NewObjectClass(ctx, socket_cid);
}
}
-
static JSValue js_net_unix_bind(
JSContext *ctx, JSValueConst this, int argc, JSValueConst *argv, int c
) {
JSModuleDef *js_init_module(JSContext *ctx, const char *name) {
JSModuleDef *mod = JS_NewCModule(ctx, name, sock_modinit);
- JSValue global = JS_GetGlobalObject(ctx);
- JSValue os = JS_GetPropertyStr(ctx, global, "os");
if (mod) {
JS_AddModuleExportList(ctx, mod, net_funcs, countof(net_funcs));
- if ( !JS_IsUndefined(os) )
- JS_SetPropertyFunctionList(ctx, os, os_socket_funcs,
- countof(os_socket_funcs));
}
- JS_FreeValue(ctx, global); JS_FreeValue(ctx, os);
return mod;
}