mirror of
https://github.com/denoland/deno.git
synced 2024-12-26 00:59:24 -05:00
243 lines
4.4 KiB
JavaScript
243 lines
4.4 KiB
JavaScript
|
// Copyright 2018-2020 the Deno authors. All rights reserved. MIT license.
|
||
|
|
||
|
((window) => {
|
||
|
const { errors } = window.__bootstrap.errors;
|
||
|
const { read, write } = window.__bootstrap.io;
|
||
|
const { close } = window.__bootstrap.resources;
|
||
|
const { sendSync, sendAsync } = window.__bootstrap.dispatchJson;
|
||
|
|
||
|
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) {
|
||
|
sendSync("op_shutdown", { rid, how });
|
||
|
return Promise.resolve();
|
||
|
}
|
||
|
|
||
|
function opAccept(
|
||
|
rid,
|
||
|
transport,
|
||
|
) {
|
||
|
return sendAsync("op_accept", { rid, transport });
|
||
|
}
|
||
|
|
||
|
function opListen(args) {
|
||
|
return sendSync("op_listen", args);
|
||
|
}
|
||
|
|
||
|
function opConnect(args) {
|
||
|
return sendAsync("op_connect", args);
|
||
|
}
|
||
|
|
||
|
function opReceive(
|
||
|
rid,
|
||
|
transport,
|
||
|
zeroCopy,
|
||
|
) {
|
||
|
return sendAsync("op_datagram_receive", { rid, transport }, zeroCopy);
|
||
|
}
|
||
|
|
||
|
function opSend(args, zeroCopy) {
|
||
|
return sendAsync("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() {
|
||
|
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() {
|
||
|
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() {
|
||
|
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);
|