diff options
Diffstat (limited to 'ext/net/01_net.js')
-rw-r--r-- | ext/net/01_net.js | 242 |
1 files changed, 84 insertions, 158 deletions
diff --git a/ext/net/01_net.js b/ext/net/01_net.js index acd8ee179..d7a093ba6 100644 --- a/ext/net/01_net.js +++ b/ext/net/01_net.js @@ -10,10 +10,10 @@ Error, ObjectPrototypeIsPrototypeOf, PromiseResolve, + Symbol, SymbolAsyncIterator, SymbolFor, TypedArrayPrototypeSubarray, - TypeError, Uint8Array, } = window.__bootstrap.primordials; @@ -38,6 +38,30 @@ return core.shutdown(rid); } + function opAccept(rid, transport) { + return core.opAsync("op_net_accept", { rid, transport }); + } + + function opListen(args) { + return ops.op_net_listen(args); + } + + function opConnect(args) { + return core.opAsync("op_net_connect", args); + } + + function opReceive(rid, transport, zeroCopy) { + return core.opAsync( + "op_dgram_recv", + { rid, transport }, + zeroCopy, + ); + } + + function opSend(args, zeroCopy) { + return core.opAsync("op_dgram_send", args, zeroCopy); + } + function resolveDns(query, recordType, options) { return core.opAsync("op_dns_resolve", { query, recordType, options }); } @@ -111,6 +135,11 @@ class UnixConn extends Conn {} + // Use symbols for method names to hide these in stable API. + // TODO(kt3k): Remove these symbols when ref/unref become stable. + const listenerRef = Symbol("listenerRef"); + const listenerUnref = Symbol("listenerUnref"); + class Listener { #rid = 0; #addr = null; @@ -130,35 +159,21 @@ return this.#addr; } - async accept() { - let promise; - switch (this.addr.transport) { - case "tcp": - promise = core.opAsync("op_net_accept_tcp", this.rid); - break; - case "unix": - promise = core.opAsync("op_net_accept_unix", this.rid); - break; - default: - throw new Error(`Unsupported transport: ${this.addr.transport}`); - } + accept() { + const promise = opAccept(this.rid, this.addr.transport); this.#promiseId = promise[promiseIdSymbol]; - if (this.#unref) core.unrefOp(this.#promiseId); - const [rid, localAddr, remoteAddr] = await promise; - this.#promiseId = null; - if (this.addr.transport == "tcp") { - localAddr.transport = "tcp"; - remoteAddr.transport = "tcp"; - return new TcpConn(rid, remoteAddr, localAddr); - } else if (this.addr.transport == "unix") { - return new UnixConn( - rid, - { transport: "unix", path: remoteAddr }, - { transport: "unix", path: localAddr }, - ); - } else { - throw new Error("unreachable"); + if (this.#unref) { + this.#unrefOpAccept(); } + return promise.then((res) => { + if (this.addr.transport == "tcp") { + return new TcpConn(res.rid, res.remoteAddr, res.localAddr); + } else if (this.addr.transport == "unix") { + return new UnixConn(res.rid, res.remoteAddr, res.localAddr); + } else { + throw new Error("unreachable"); + } + }); } async next() { @@ -190,15 +205,22 @@ return this; } - ref() { + [listenerRef]() { this.#unref = false; + this.#refOpAccept(); + } + + [listenerUnref]() { + this.#unref = true; + this.#unrefOpAccept(); + } + + #refOpAccept() { if (typeof this.#promiseId === "number") { core.refOp(this.#promiseId); } } - - unref() { - this.#unref = true; + #unrefOpAccept() { if (typeof this.#promiseId === "number") { core.unrefOp(this.#promiseId); } @@ -225,54 +247,18 @@ async receive(p) { const buf = p || new Uint8Array(this.bufSize); - let nread; - let remoteAddr; - switch (this.addr.transport) { - case "udp": { - [nread, remoteAddr] = await core.opAsync( - "op_net_recv_udp", - this.rid, - buf, - ); - remoteAddr.transport = "udp"; - break; - } - case "unixpacket": { - let path; - [nread, path] = await core.opAsync( - "op_net_recv_unixpacket", - this.rid, - buf, - ); - remoteAddr = { transport: "unixpacket", path }; - break; - } - default: - throw new Error(`Unsupported transport: ${this.addr.transport}`); - } - const sub = TypedArrayPrototypeSubarray(buf, 0, nread); + const { size, remoteAddr } = await opReceive( + this.rid, + this.addr.transport, + buf, + ); + const sub = TypedArrayPrototypeSubarray(buf, 0, size); return [sub, remoteAddr]; } - async send(p, opts) { - switch (this.addr.transport) { - case "udp": - return await core.opAsync( - "op_net_send_udp", - this.rid, - { hostname: opts.hostname ?? "127.0.0.1", port: opts.port }, - p, - ); - case "unixpacket": - return await core.opAsync( - "op_net_send_unixpacket", - this.rid, - opts.path, - p, - ); - default: - throw new Error(`Unsupported transport: ${this.addr.transport}`); - } + send(p, addr) { + const args = { hostname: "127.0.0.1", ...addr, rid: this.rid }; + return opSend(args, p); } close() { @@ -296,100 +282,40 @@ } } - function listen(args) { - switch (args.transport ?? "tcp") { - case "tcp": { - const [rid, addr] = ops.op_net_listen_tcp({ - hostname: args.hostname ?? "0.0.0.0", - port: args.port, - }); - addr.transport = "tcp"; - return new Listener(rid, addr); - } - case "unix": { - const [rid, path] = ops.op_net_listen_unix(args.path); - const addr = { - transport: "unix", - path, - }; - return new Listener(rid, addr); - } - default: - throw new TypeError(`Unsupported transport: '${transport}'`); - } - } + function listen({ hostname, ...options }, constructor = Listener) { + const res = opListen({ + transport: "tcp", + hostname: typeof hostname === "undefined" ? "0.0.0.0" : hostname, + ...options, + }); - function listenDatagram(args) { - switch (args.transport) { - case "udp": { - const [rid, addr] = ops.op_net_listen_udp( - { - hostname: args.hostname ?? "127.0.0.1", - port: args.port, - }, - args.reuseAddress ?? false, - ); - addr.transport = "udp"; - return new Datagram(rid, addr); - } - case "unixpacket": { - const [rid, path] = ops.op_net_listen_unixpacket(args.path); - const addr = { - transport: "unixpacket", - path, - }; - return new Datagram(rid, addr); - } - default: - throw new TypeError(`Unsupported transport: '${transport}'`); - } + return new constructor(res.rid, res.localAddr); } - async function connect(args) { - switch (args.transport ?? "tcp") { - case "tcp": { - const [rid, localAddr, remoteAddr] = await core.opAsync( - "op_net_connect_tcp", - { - hostname: args.hostname ?? "127.0.0.1", - port: args.port, - }, - ); - localAddr.transport = "tcp"; - remoteAddr.transport = "tcp"; - return new TcpConn(rid, remoteAddr, localAddr); - } - case "unix": { - const [rid, localAddr, remoteAddr] = await core.opAsync( - "op_net_connect_unix", - args.path, - ); - return new UnixConn( - rid, - { transport: "unix", path: remoteAddr }, - { transport: "unix", path: localAddr }, - ); - } - default: - throw new TypeError(`Unsupported transport: '${transport}'`); + async function connect(options) { + if (options.transport === "unix") { + const res = await opConnect(options); + return new UnixConn(res.rid, res.remoteAddr, res.localAddr); } - } - function setup(unstable) { - if (!unstable) { - delete Listener.prototype.ref; - delete Listener.prototype.unref; - } + const res = await opConnect({ + transport: "tcp", + hostname: "127.0.0.1", + ...options, + }); + return new TcpConn(res.rid, res.remoteAddr, res.localAddr); } window.__bootstrap.net = { - setup, connect, Conn, TcpConn, UnixConn, + opConnect, listen, - listenDatagram, + listenerRef, + listenerUnref, + opListen, Listener, shutdown, Datagram, |