diff options
author | Nayeem Rahman <nayeemrmn99@gmail.com> | 2020-12-17 16:37:57 +0000 |
---|---|---|
committer | GitHub <noreply@github.com> | 2020-12-17 17:37:57 +0100 |
commit | ffb5f7a4e1d5d4ac488058ca3ec3c0805587fe44 (patch) | |
tree | dc7b79a699732680fa309d97e5b4c2bc5f486a4a /runtime/js/30_net.js | |
parent | 55dc467b419b8e5897b1c832b04d63e383253d84 (diff) |
refactor: Rename runtime/rt to runtime/js (#8806)
Diffstat (limited to 'runtime/js/30_net.js')
-rw-r--r-- | runtime/js/30_net.js | 227 |
1 files changed, 227 insertions, 0 deletions
diff --git a/runtime/js/30_net.js b/runtime/js/30_net.js new file mode 100644 index 000000000..7009f6f8d --- /dev/null +++ b/runtime/js/30_net.js @@ -0,0 +1,227 @@ +// Copyright 2018-2020 the Deno authors. All rights reserved. MIT license. + +((window) => { + const core = window.Deno.core; + const { errors } = window.__bootstrap.errors; + const { read, write } = window.__bootstrap.io; + + const ShutdownMode = { + // See http://man7.org/linux/man-pages/man2/shutdown.2.html + // Corresponding to SHUT_RD, SHUT_WR, SHUT_RDWR + 0: "Read", + 1: "Write", + 2: "ReadWrite", + Read: 0, // TODO: nonsense, remove me. + Write: 1, + ReadWrite: 2, // unused + }; + + function shutdown(rid, how) { + return core.jsonOpAsync("op_shutdown", { rid, how }); + } + + function opAccept(rid, transport) { + return core.jsonOpAsync("op_accept", { rid, transport }); + } + + function opListen(args) { + return core.jsonOpSync("op_listen", args); + } + + function opConnect(args) { + return core.jsonOpAsync("op_connect", args); + } + + function opReceive(rid, transport, zeroCopy) { + return core.jsonOpAsync( + "op_datagram_receive", + { rid, transport }, + zeroCopy, + ); + } + + function opSend(args, zeroCopy) { + return core.jsonOpAsync("op_datagram_send", args, zeroCopy); + } + + class Conn { + #rid = 0; + #remoteAddr = null; + #localAddr = null; + constructor(rid, remoteAddr, localAddr) { + this.#rid = rid; + this.#remoteAddr = remoteAddr; + this.#localAddr = localAddr; + } + + get rid() { + return this.#rid; + } + + get remoteAddr() { + return this.#remoteAddr; + } + + get localAddr() { + return this.#localAddr; + } + + write(p) { + return write(this.rid, p); + } + + read(p) { + return read(this.rid, p); + } + + close() { + core.close(this.rid); + } + + // TODO(lucacasonato): make this unavailable in stable + closeWrite() { + shutdown(this.rid, ShutdownMode.Write); + } + } + + class Listener { + #rid = 0; + #addr = null; + + constructor(rid, addr) { + this.#rid = rid; + this.#addr = addr; + } + + get rid() { + return this.#rid; + } + + get addr() { + return this.#addr; + } + + async accept() { + const res = await opAccept(this.rid, this.addr.transport); + return new Conn(res.rid, res.remoteAddr, res.localAddr); + } + + async next() { + let conn; + try { + conn = await this.accept(); + } catch (error) { + if (error instanceof errors.BadResource) { + return { value: undefined, done: true }; + } + throw error; + } + return { value: conn, done: false }; + } + + return(value) { + this.close(); + return Promise.resolve({ value, done: true }); + } + + close() { + core.close(this.rid); + } + + [Symbol.asyncIterator]() { + return this; + } + } + + class Datagram { + #rid = 0; + #addr = null; + + constructor(rid, addr, bufSize = 1024) { + this.#rid = rid; + this.#addr = addr; + this.bufSize = bufSize; + } + + get rid() { + return this.#rid; + } + + get addr() { + return this.#addr; + } + + async receive(p) { + const buf = p || new Uint8Array(this.bufSize); + const { size, remoteAddr } = await opReceive( + this.rid, + this.addr.transport, + buf, + ); + const sub = buf.subarray(0, size); + return [sub, remoteAddr]; + } + + send(p, addr) { + const remote = { hostname: "127.0.0.1", ...addr }; + + const args = { ...remote, rid: this.rid }; + return opSend(args, p); + } + + close() { + core.close(this.rid); + } + + async *[Symbol.asyncIterator]() { + while (true) { + try { + yield await this.receive(); + } catch (err) { + if (err instanceof errors.BadResource) { + break; + } + throw err; + } + } + } + } + + function listen({ hostname, ...options }) { + const res = opListen({ + transport: "tcp", + hostname: typeof hostname === "undefined" ? "0.0.0.0" : hostname, + ...options, + }); + + return new Listener(res.rid, res.localAddr); + } + + async function connect(options) { + let res; + + if (options.transport === "unix") { + res = await opConnect(options); + } else { + res = await opConnect({ + transport: "tcp", + hostname: "127.0.0.1", + ...options, + }); + } + + return new Conn(res.rid, res.remoteAddr, res.localAddr); + } + + window.__bootstrap.net = { + connect, + Conn, + opConnect, + listen, + opListen, + Listener, + shutdown, + ShutdownMode, + Datagram, + }; +})(this); |