2020-01-02 15:13:47 -05:00
|
|
|
// Copyright 2018-2020 the Deno authors. All rights reserved. MIT license.
|
2020-07-07 04:45:39 +03:00
|
|
|
|
2020-03-10 19:14:22 +00:00
|
|
|
import { errors } from "./errors.ts";
|
2020-07-08 19:26:39 +10:00
|
|
|
import type { Reader, Writer, Closer } from "./io.ts";
|
2020-03-09 15:18:02 +01:00
|
|
|
import { read, write } from "./ops/io.ts";
|
2020-03-08 13:09:22 +01:00
|
|
|
import { close } from "./ops/resources.ts";
|
2020-03-10 00:22:15 +01:00
|
|
|
import * as netOps from "./ops/net.ts";
|
2020-07-08 19:26:39 +10:00
|
|
|
import type { Addr } from "./ops/net.ts";
|
|
|
|
export type { ShutdownMode, NetAddr, UnixAddr } from "./ops/net.ts";
|
|
|
|
export { shutdown } from "./ops/net.ts";
|
2018-10-03 23:58:29 -04:00
|
|
|
|
2020-03-23 22:02:51 +00:00
|
|
|
export interface DatagramConn extends AsyncIterable<[Uint8Array, Addr]> {
|
2020-02-21 17:26:54 +01:00
|
|
|
receive(p?: Uint8Array): Promise<[Uint8Array, Addr]>;
|
|
|
|
|
2020-06-13 22:14:31 +08:00
|
|
|
send(p: Uint8Array, addr: Addr): Promise<number>;
|
2020-02-21 17:26:54 +01:00
|
|
|
|
|
|
|
close(): void;
|
|
|
|
|
|
|
|
addr: Addr;
|
|
|
|
|
2020-04-15 11:44:09 +01:00
|
|
|
[Symbol.asyncIterator](): AsyncIterableIterator<[Uint8Array, Addr]>;
|
2020-02-21 17:26:54 +01:00
|
|
|
}
|
|
|
|
|
2020-03-10 19:14:22 +00:00
|
|
|
export interface Listener extends AsyncIterable<Conn> {
|
2018-10-03 23:58:29 -04:00
|
|
|
accept(): Promise<Conn>;
|
|
|
|
|
|
|
|
close(): void;
|
|
|
|
|
2020-01-18 21:49:55 +01:00
|
|
|
addr: Addr;
|
2019-05-01 16:58:09 -04:00
|
|
|
|
2020-06-09 00:24:51 +08:00
|
|
|
rid: number;
|
|
|
|
|
2020-04-15 11:44:09 +01:00
|
|
|
[Symbol.asyncIterator](): AsyncIterableIterator<Conn>;
|
2018-10-03 23:58:29 -04:00
|
|
|
}
|
|
|
|
|
2019-09-23 14:40:38 -04:00
|
|
|
export class ConnImpl implements Conn {
|
2018-10-03 23:58:29 -04:00
|
|
|
constructor(
|
2018-10-11 00:59:36 +09:00
|
|
|
readonly rid: number,
|
2020-01-18 21:49:55 +01:00
|
|
|
readonly remoteAddr: Addr,
|
|
|
|
readonly localAddr: Addr
|
2018-10-03 23:58:29 -04:00
|
|
|
) {}
|
|
|
|
|
2018-11-08 01:18:21 -05:00
|
|
|
write(p: Uint8Array): Promise<number> {
|
2018-10-11 00:59:36 +09:00
|
|
|
return write(this.rid, p);
|
2018-10-03 23:58:29 -04:00
|
|
|
}
|
|
|
|
|
2020-04-28 17:40:43 +01:00
|
|
|
read(p: Uint8Array): Promise<number | null> {
|
2018-10-11 00:59:36 +09:00
|
|
|
return read(this.rid, p);
|
2018-10-03 23:58:29 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
close(): void {
|
2018-10-11 00:59:36 +09:00
|
|
|
close(this.rid);
|
2018-10-03 23:58:29 -04:00
|
|
|
}
|
|
|
|
|
2020-04-30 17:23:40 +02:00
|
|
|
// TODO(lucacasonato): make this unavailable in stable
|
2018-10-03 23:58:29 -04:00
|
|
|
closeWrite(): void {
|
2020-03-10 00:22:15 +01:00
|
|
|
netOps.shutdown(this.rid, netOps.ShutdownMode.Write);
|
2018-10-03 23:58:29 -04:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2019-10-21 20:38:28 +02:00
|
|
|
export class ListenerImpl implements Listener {
|
2020-03-10 19:14:22 +00:00
|
|
|
constructor(readonly rid: number, readonly addr: Addr) {}
|
2019-03-10 04:30:38 +11:00
|
|
|
|
|
|
|
async accept(): Promise<Conn> {
|
2020-03-23 22:02:51 +00:00
|
|
|
const res = await netOps.accept(this.rid, this.addr.transport);
|
2019-08-27 17:35:32 +02:00
|
|
|
return new ConnImpl(res.rid, res.remoteAddr, res.localAddr);
|
2019-03-10 04:30:38 +11:00
|
|
|
}
|
|
|
|
|
2020-04-29 01:08:02 +02:00
|
|
|
async next(): Promise<IteratorResult<Conn>> {
|
|
|
|
let conn: 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?: Conn): Promise<IteratorResult<Conn>> {
|
|
|
|
this.close();
|
|
|
|
return Promise.resolve({ value, done: true });
|
|
|
|
}
|
|
|
|
|
2019-03-10 04:30:38 +11:00
|
|
|
close(): void {
|
|
|
|
close(this.rid);
|
|
|
|
}
|
|
|
|
|
2020-04-29 01:08:02 +02:00
|
|
|
[Symbol.asyncIterator](): AsyncIterableIterator<Conn> {
|
|
|
|
return this;
|
2019-05-01 16:58:09 -04:00
|
|
|
}
|
2018-10-05 09:16:24 -07:00
|
|
|
}
|
|
|
|
|
2020-03-23 22:02:51 +00:00
|
|
|
export class DatagramImpl implements DatagramConn {
|
2020-02-21 17:26:54 +01:00
|
|
|
constructor(
|
|
|
|
readonly rid: number,
|
|
|
|
readonly addr: Addr,
|
2020-03-10 19:14:22 +00:00
|
|
|
public bufSize: number = 1024
|
2020-02-21 17:26:54 +01:00
|
|
|
) {}
|
|
|
|
|
|
|
|
async receive(p?: Uint8Array): Promise<[Uint8Array, Addr]> {
|
|
|
|
const buf = p || new Uint8Array(this.bufSize);
|
2020-03-23 22:02:51 +00:00
|
|
|
const { size, remoteAddr } = await netOps.receive(
|
|
|
|
this.rid,
|
|
|
|
this.addr.transport,
|
|
|
|
buf
|
|
|
|
);
|
2020-02-21 17:26:54 +01:00
|
|
|
const sub = buf.subarray(0, size);
|
|
|
|
return [sub, remoteAddr];
|
|
|
|
}
|
|
|
|
|
2020-07-07 04:45:39 +03:00
|
|
|
send(p: Uint8Array, addr: Addr): Promise<number> {
|
2020-05-13 22:03:04 +10:00
|
|
|
const remote = { hostname: "127.0.0.1", ...addr };
|
2020-03-23 22:02:51 +00:00
|
|
|
|
2020-02-21 17:26:54 +01:00
|
|
|
const args = { ...remote, rid: this.rid };
|
2020-07-07 04:45:39 +03:00
|
|
|
return netOps.send(args as netOps.SendRequest, p);
|
2020-02-21 17:26:54 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
close(): void {
|
|
|
|
close(this.rid);
|
|
|
|
}
|
|
|
|
|
2020-04-15 11:44:09 +01:00
|
|
|
async *[Symbol.asyncIterator](): AsyncIterableIterator<[Uint8Array, Addr]> {
|
2020-03-10 19:14:22 +00:00
|
|
|
while (true) {
|
|
|
|
try {
|
|
|
|
yield await this.receive();
|
2020-07-07 04:45:39 +03:00
|
|
|
} catch (err) {
|
|
|
|
if (err instanceof errors.BadResource) {
|
2020-03-10 19:14:22 +00:00
|
|
|
break;
|
2020-02-21 17:26:54 +01:00
|
|
|
}
|
2020-07-07 04:45:39 +03:00
|
|
|
throw err;
|
2020-03-10 19:14:22 +00:00
|
|
|
}
|
|
|
|
}
|
2020-02-21 17:26:54 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2019-03-10 04:30:38 +11:00
|
|
|
export interface Conn extends Reader, Writer, Closer {
|
2020-01-18 21:49:55 +01:00
|
|
|
localAddr: Addr;
|
|
|
|
remoteAddr: Addr;
|
2019-03-10 04:30:38 +11:00
|
|
|
rid: number;
|
|
|
|
closeWrite(): void;
|
2018-10-05 09:16:24 -07:00
|
|
|
}
|
|
|
|
|
2019-09-20 18:32:18 -04:00
|
|
|
export interface ListenOptions {
|
|
|
|
port: number;
|
|
|
|
hostname?: string;
|
2020-04-30 17:23:40 +02:00
|
|
|
transport?: "tcp";
|
2019-09-20 18:32:18 -04:00
|
|
|
}
|
|
|
|
|
2020-02-21 17:26:54 +01:00
|
|
|
export function listen(
|
|
|
|
options: ListenOptions & { transport?: "tcp" }
|
|
|
|
): Listener;
|
2020-04-30 17:23:40 +02:00
|
|
|
export function listen(options: ListenOptions): Listener {
|
|
|
|
const res = netOps.listen({
|
|
|
|
transport: "tcp",
|
2020-05-13 18:48:41 +05:30
|
|
|
hostname: "0.0.0.0",
|
2020-04-30 17:23:40 +02:00
|
|
|
...(options as ListenOptions),
|
|
|
|
});
|
2020-04-28 21:46:39 +02:00
|
|
|
|
|
|
|
return new ListenerImpl(res.rid, res.localAddr);
|
|
|
|
}
|
|
|
|
|
2020-01-18 18:35:12 +01:00
|
|
|
export interface ConnectOptions {
|
2019-09-20 18:32:18 -04:00
|
|
|
port: number;
|
|
|
|
hostname?: string;
|
2020-03-23 22:02:51 +00:00
|
|
|
transport?: "tcp";
|
2019-09-20 18:32:18 -04:00
|
|
|
}
|
2020-03-23 22:02:51 +00:00
|
|
|
export interface UnixConnectOptions {
|
|
|
|
transport: "unix";
|
2020-04-28 21:07:59 +04:30
|
|
|
path: string;
|
2020-03-23 22:02:51 +00:00
|
|
|
}
|
|
|
|
export async function connect(options: UnixConnectOptions): Promise<Conn>;
|
|
|
|
export async function connect(options: ConnectOptions): Promise<Conn>;
|
|
|
|
export async function connect(
|
|
|
|
options: ConnectOptions | UnixConnectOptions
|
|
|
|
): Promise<Conn> {
|
|
|
|
let res;
|
|
|
|
|
|
|
|
if (options.transport === "unix") {
|
|
|
|
res = await netOps.connect(options);
|
|
|
|
} else {
|
|
|
|
res = await netOps.connect({
|
|
|
|
transport: "tcp",
|
|
|
|
hostname: "127.0.0.1",
|
2020-03-29 04:03:49 +11:00
|
|
|
...options,
|
2020-03-23 22:02:51 +00:00
|
|
|
});
|
|
|
|
}
|
2019-09-20 18:32:18 -04:00
|
|
|
|
2019-08-26 14:50:21 +02:00
|
|
|
return new ConnImpl(res.rid, res.remoteAddr!, res.localAddr!);
|
2018-10-03 23:58:29 -04:00
|
|
|
}
|