// 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, Write: 1, ReadWrite: 2, // unused }; function shutdown(rid, how) { core.jsonOpSync("op_shutdown", { rid, how }); return Promise.resolve(); } 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(options) { const res = opListen({ transport: "tcp", hostname: "0.0.0.0", ...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);