mirror of
https://github.com/denoland/deno.git
synced 2024-11-28 16:20:57 -05:00
feat: Add "deno_net" extension (#11150)
This commits moves implementation of net related APIs available on "Deno" namespace to "deno_net" extension. Following APIs were moved: - Deno.listen() - Deno.connect() - Deno.listenTls() - Deno.serveHttp() - Deno.shutdown() - Deno.resolveDns() - Deno.listenDatagram() - Deno.startTls() - Deno.Conn - Deno.Listener - Deno.DatagramConn
This commit is contained in:
parent
30cba24848
commit
38a7128cdd
34 changed files with 1049 additions and 679 deletions
29
Cargo.lock
generated
29
Cargo.lock
generated
|
@ -536,6 +536,7 @@ dependencies = [
|
||||||
"deno_doc",
|
"deno_doc",
|
||||||
"deno_fetch",
|
"deno_fetch",
|
||||||
"deno_lint",
|
"deno_lint",
|
||||||
|
"deno_net",
|
||||||
"deno_runtime",
|
"deno_runtime",
|
||||||
"deno_timers",
|
"deno_timers",
|
||||||
"deno_url",
|
"deno_url",
|
||||||
|
@ -702,17 +703,37 @@ dependencies = [
|
||||||
"swc_ecmascript",
|
"swc_ecmascript",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "deno_net"
|
||||||
|
version = "0.1.0"
|
||||||
|
dependencies = [
|
||||||
|
"bytes",
|
||||||
|
"deno_core",
|
||||||
|
"http",
|
||||||
|
"hyper",
|
||||||
|
"lazy_static",
|
||||||
|
"log",
|
||||||
|
"rustls",
|
||||||
|
"serde",
|
||||||
|
"tokio",
|
||||||
|
"tokio-util",
|
||||||
|
"trust-dns-proto",
|
||||||
|
"trust-dns-resolver",
|
||||||
|
"webpki",
|
||||||
|
"webpki-roots",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "deno_runtime"
|
name = "deno_runtime"
|
||||||
version = "0.18.0"
|
version = "0.18.0"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"atty",
|
"atty",
|
||||||
"bytes",
|
|
||||||
"deno_broadcast_channel",
|
"deno_broadcast_channel",
|
||||||
"deno_console",
|
"deno_console",
|
||||||
"deno_core",
|
"deno_core",
|
||||||
"deno_crypto",
|
"deno_crypto",
|
||||||
"deno_fetch",
|
"deno_fetch",
|
||||||
|
"deno_net",
|
||||||
"deno_timers",
|
"deno_timers",
|
||||||
"deno_url",
|
"deno_url",
|
||||||
"deno_web",
|
"deno_web",
|
||||||
|
@ -735,18 +756,12 @@ dependencies = [
|
||||||
"percent-encoding",
|
"percent-encoding",
|
||||||
"regex",
|
"regex",
|
||||||
"ring",
|
"ring",
|
||||||
"rustls",
|
|
||||||
"serde",
|
"serde",
|
||||||
"sys-info",
|
"sys-info",
|
||||||
"termcolor",
|
"termcolor",
|
||||||
"test_util",
|
"test_util",
|
||||||
"tokio",
|
"tokio",
|
||||||
"tokio-util",
|
|
||||||
"trust-dns-proto",
|
|
||||||
"trust-dns-resolver",
|
|
||||||
"uuid",
|
"uuid",
|
||||||
"webpki",
|
|
||||||
"webpki-roots",
|
|
||||||
"winapi 0.3.9",
|
"winapi 0.3.9",
|
||||||
"winres",
|
"winres",
|
||||||
]
|
]
|
||||||
|
|
|
@ -12,6 +12,7 @@ members = [
|
||||||
"extensions/console",
|
"extensions/console",
|
||||||
"extensions/crypto",
|
"extensions/crypto",
|
||||||
"extensions/fetch",
|
"extensions/fetch",
|
||||||
|
"extensions/net",
|
||||||
"extensions/timers",
|
"extensions/timers",
|
||||||
"extensions/url",
|
"extensions/url",
|
||||||
"extensions/web",
|
"extensions/web",
|
||||||
|
|
|
@ -25,6 +25,7 @@ deno_console = { version = "0.10.0", path = "../extensions/console" }
|
||||||
deno_core = { version = "0.92.0", path = "../core" }
|
deno_core = { version = "0.92.0", path = "../core" }
|
||||||
deno_crypto = { version = "0.24.0", path = "../extensions/crypto" }
|
deno_crypto = { version = "0.24.0", path = "../extensions/crypto" }
|
||||||
deno_fetch = { version = "0.32.0", path = "../extensions/fetch" }
|
deno_fetch = { version = "0.32.0", path = "../extensions/fetch" }
|
||||||
|
deno_net = { version = "0.1.0", path = "../extensions/net" }
|
||||||
deno_timers = { version = "0.8.0", path = "../extensions/timers" }
|
deno_timers = { version = "0.8.0", path = "../extensions/timers" }
|
||||||
deno_url = { version = "0.10.0", path = "../extensions/url" }
|
deno_url = { version = "0.10.0", path = "../extensions/url" }
|
||||||
deno_web = { version = "0.41.0", path = "../extensions/web" }
|
deno_web = { version = "0.41.0", path = "../extensions/web" }
|
||||||
|
|
11
cli/build.rs
11
cli/build.rs
|
@ -68,6 +68,9 @@ fn create_compiler_snapshot(
|
||||||
"deno.broadcast_channel",
|
"deno.broadcast_channel",
|
||||||
deno_broadcast_channel::get_declaration(),
|
deno_broadcast_channel::get_declaration(),
|
||||||
);
|
);
|
||||||
|
op_crate_libs.insert("deno.net", deno_net::get_declaration());
|
||||||
|
op_crate_libs
|
||||||
|
.insert("deno.net_unstable", deno_net::get_unstable_declaration());
|
||||||
|
|
||||||
// ensure we invalidate the build properly.
|
// ensure we invalidate the build properly.
|
||||||
for (_, path) in op_crate_libs.iter() {
|
for (_, path) in op_crate_libs.iter() {
|
||||||
|
@ -302,6 +305,14 @@ fn main() {
|
||||||
"cargo:rustc-env=DENO_BROADCAST_CHANNEL_LIB_PATH={}",
|
"cargo:rustc-env=DENO_BROADCAST_CHANNEL_LIB_PATH={}",
|
||||||
deno_broadcast_channel::get_declaration().display()
|
deno_broadcast_channel::get_declaration().display()
|
||||||
);
|
);
|
||||||
|
println!(
|
||||||
|
"cargo:rustc-env=DENO_NET_LIB_PATH={}",
|
||||||
|
deno_net::get_declaration().display()
|
||||||
|
);
|
||||||
|
println!(
|
||||||
|
"cargo:rustc-env=DENO_NET_UNSTABLE_LIB_PATH={}",
|
||||||
|
deno_net::get_unstable_declaration().display()
|
||||||
|
);
|
||||||
|
|
||||||
println!("cargo:rustc-env=TARGET={}", env::var("TARGET").unwrap());
|
println!("cargo:rustc-env=TARGET={}", env::var("TARGET").unwrap());
|
||||||
println!("cargo:rustc-env=PROFILE={}", env::var("PROFILE").unwrap());
|
println!("cargo:rustc-env=PROFILE={}", env::var("PROFILE").unwrap());
|
||||||
|
|
144
cli/dts/lib.deno.ns.d.ts
vendored
144
cli/dts/lib.deno.ns.d.ts
vendored
|
@ -2,6 +2,7 @@
|
||||||
|
|
||||||
/// <reference no-default-lib="true" />
|
/// <reference no-default-lib="true" />
|
||||||
/// <reference lib="esnext" />
|
/// <reference lib="esnext" />
|
||||||
|
/// <reference lib="deno.net" />
|
||||||
|
|
||||||
/** Deno provides extra properties on `import.meta`. These are included here
|
/** Deno provides extra properties on `import.meta`. These are included here
|
||||||
* to ensure that these are still available when using the Deno namespace in
|
* to ensure that these are still available when using the Deno namespace in
|
||||||
|
@ -1784,149 +1785,6 @@ declare namespace Deno {
|
||||||
* Requires `allow-write` permission. */
|
* Requires `allow-write` permission. */
|
||||||
export function truncate(name: string, len?: number): Promise<void>;
|
export function truncate(name: string, len?: number): Promise<void>;
|
||||||
|
|
||||||
export interface NetAddr {
|
|
||||||
transport: "tcp" | "udp";
|
|
||||||
hostname: string;
|
|
||||||
port: number;
|
|
||||||
}
|
|
||||||
|
|
||||||
export interface UnixAddr {
|
|
||||||
transport: "unix" | "unixpacket";
|
|
||||||
path: string;
|
|
||||||
}
|
|
||||||
|
|
||||||
export type Addr = NetAddr | UnixAddr;
|
|
||||||
|
|
||||||
/** A generic network listener for stream-oriented protocols. */
|
|
||||||
export interface Listener extends AsyncIterable<Conn> {
|
|
||||||
/** Waits for and resolves to the next connection to the `Listener`. */
|
|
||||||
accept(): Promise<Conn>;
|
|
||||||
/** Close closes the listener. Any pending accept promises will be rejected
|
|
||||||
* with errors. */
|
|
||||||
close(): void;
|
|
||||||
/** Return the address of the `Listener`. */
|
|
||||||
readonly addr: Addr;
|
|
||||||
|
|
||||||
/** Return the rid of the `Listener`. */
|
|
||||||
readonly rid: number;
|
|
||||||
|
|
||||||
[Symbol.asyncIterator](): AsyncIterableIterator<Conn>;
|
|
||||||
}
|
|
||||||
|
|
||||||
export interface Conn extends Reader, Writer, Closer {
|
|
||||||
/** The local address of the connection. */
|
|
||||||
readonly localAddr: Addr;
|
|
||||||
/** The remote address of the connection. */
|
|
||||||
readonly remoteAddr: Addr;
|
|
||||||
/** The resource ID of the connection. */
|
|
||||||
readonly rid: number;
|
|
||||||
/** Shuts down (`shutdown(2)`) the write side of the connection. Most
|
|
||||||
* callers should just use `close()`. */
|
|
||||||
closeWrite(): Promise<void>;
|
|
||||||
}
|
|
||||||
|
|
||||||
export interface ListenOptions {
|
|
||||||
/** The port to listen on. */
|
|
||||||
port: number;
|
|
||||||
/** A literal IP address or host name that can be resolved to an IP address.
|
|
||||||
* If not specified, defaults to `0.0.0.0`. */
|
|
||||||
hostname?: string;
|
|
||||||
}
|
|
||||||
|
|
||||||
/** Listen announces on the local transport address.
|
|
||||||
*
|
|
||||||
* ```ts
|
|
||||||
* const listener1 = Deno.listen({ port: 80 })
|
|
||||||
* const listener2 = Deno.listen({ hostname: "192.0.2.1", port: 80 })
|
|
||||||
* const listener3 = Deno.listen({ hostname: "[2001:db8::1]", port: 80 });
|
|
||||||
* const listener4 = Deno.listen({ hostname: "golang.org", port: 80, transport: "tcp" });
|
|
||||||
* ```
|
|
||||||
*
|
|
||||||
* Requires `allow-net` permission. */
|
|
||||||
export function listen(
|
|
||||||
options: ListenOptions & { transport?: "tcp" },
|
|
||||||
): Listener;
|
|
||||||
|
|
||||||
export interface ListenTlsOptions extends ListenOptions {
|
|
||||||
/** Server certificate file. */
|
|
||||||
certFile: string;
|
|
||||||
/** Server public key file. */
|
|
||||||
keyFile: string;
|
|
||||||
|
|
||||||
transport?: "tcp";
|
|
||||||
}
|
|
||||||
|
|
||||||
/** Listen announces on the local transport address over TLS (transport layer
|
|
||||||
* security).
|
|
||||||
*
|
|
||||||
* ```ts
|
|
||||||
* const lstnr = Deno.listenTls({ port: 443, certFile: "./server.crt", keyFile: "./server.key" });
|
|
||||||
* ```
|
|
||||||
*
|
|
||||||
* Requires `allow-net` permission. */
|
|
||||||
export function listenTls(options: ListenTlsOptions): Listener;
|
|
||||||
|
|
||||||
export interface ConnectOptions {
|
|
||||||
/** The port to connect to. */
|
|
||||||
port: number;
|
|
||||||
/** A literal IP address or host name that can be resolved to an IP address.
|
|
||||||
* If not specified, defaults to `127.0.0.1`. */
|
|
||||||
hostname?: string;
|
|
||||||
transport?: "tcp";
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Connects to the hostname (default is "127.0.0.1") and port on the named
|
|
||||||
* transport (default is "tcp"), and resolves to the connection (`Conn`).
|
|
||||||
*
|
|
||||||
* ```ts
|
|
||||||
* const conn1 = await Deno.connect({ port: 80 });
|
|
||||||
* const conn2 = await Deno.connect({ hostname: "192.0.2.1", port: 80 });
|
|
||||||
* const conn3 = await Deno.connect({ hostname: "[2001:db8::1]", port: 80 });
|
|
||||||
* const conn4 = await Deno.connect({ hostname: "golang.org", port: 80, transport: "tcp" });
|
|
||||||
* ```
|
|
||||||
*
|
|
||||||
* Requires `allow-net` permission for "tcp". */
|
|
||||||
export function connect(options: ConnectOptions): Promise<Conn>;
|
|
||||||
|
|
||||||
export interface ConnectTlsOptions {
|
|
||||||
/** The port to connect to. */
|
|
||||||
port: number;
|
|
||||||
/** A literal IP address or host name that can be resolved to an IP address.
|
|
||||||
* If not specified, defaults to `127.0.0.1`. */
|
|
||||||
hostname?: string;
|
|
||||||
/** Server certificate file. */
|
|
||||||
certFile?: string;
|
|
||||||
}
|
|
||||||
|
|
||||||
/** Establishes a secure connection over TLS (transport layer security) using
|
|
||||||
* an optional cert file, hostname (default is "127.0.0.1") and port. The
|
|
||||||
* cert file is optional and if not included Mozilla's root certificates will
|
|
||||||
* be used (see also https://github.com/ctz/webpki-roots for specifics)
|
|
||||||
*
|
|
||||||
* ```ts
|
|
||||||
* const conn1 = await Deno.connectTls({ port: 80 });
|
|
||||||
* const conn2 = await Deno.connectTls({ certFile: "./certs/my_custom_root_CA.pem", hostname: "192.0.2.1", port: 80 });
|
|
||||||
* const conn3 = await Deno.connectTls({ hostname: "[2001:db8::1]", port: 80 });
|
|
||||||
* const conn4 = await Deno.connectTls({ certFile: "./certs/my_custom_root_CA.pem", hostname: "golang.org", port: 80});
|
|
||||||
* ```
|
|
||||||
*
|
|
||||||
* Requires `allow-net` permission.
|
|
||||||
*/
|
|
||||||
export function connectTls(options: ConnectTlsOptions): Promise<Conn>;
|
|
||||||
|
|
||||||
/** Shutdown socket send operations.
|
|
||||||
*
|
|
||||||
* Matches behavior of POSIX shutdown(3).
|
|
||||||
*
|
|
||||||
* ```ts
|
|
||||||
* const listener = Deno.listen({ port: 80 });
|
|
||||||
* const conn = await listener.accept();
|
|
||||||
* Deno.shutdown(conn.rid);
|
|
||||||
* ```
|
|
||||||
*/
|
|
||||||
export function shutdown(rid: number): Promise<void>;
|
|
||||||
|
|
||||||
export interface Metrics {
|
export interface Metrics {
|
||||||
opsDispatched: number;
|
opsDispatched: number;
|
||||||
opsDispatchedSync: number;
|
opsDispatchedSync: number;
|
||||||
|
|
257
cli/dts/lib.deno.unstable.d.ts
vendored
257
cli/dts/lib.deno.unstable.d.ts
vendored
|
@ -2,6 +2,7 @@
|
||||||
|
|
||||||
/// <reference no-default-lib="true" />
|
/// <reference no-default-lib="true" />
|
||||||
/// <reference lib="deno.ns" />
|
/// <reference lib="deno.ns" />
|
||||||
|
/// <reference lib="deno.net_unstable" />
|
||||||
|
|
||||||
declare namespace Deno {
|
declare namespace Deno {
|
||||||
/**
|
/**
|
||||||
|
@ -812,232 +813,6 @@ declare namespace Deno {
|
||||||
mtime: number | Date,
|
mtime: number | Date,
|
||||||
): Promise<void>;
|
): Promise<void>;
|
||||||
|
|
||||||
/** The type of the resource record.
|
|
||||||
* Only the listed types are supported currently. */
|
|
||||||
export type RecordType =
|
|
||||||
| "A"
|
|
||||||
| "AAAA"
|
|
||||||
| "ANAME"
|
|
||||||
| "CNAME"
|
|
||||||
| "MX"
|
|
||||||
| "PTR"
|
|
||||||
| "SRV"
|
|
||||||
| "TXT";
|
|
||||||
|
|
||||||
export interface ResolveDnsOptions {
|
|
||||||
/** The name server to be used for lookups.
|
|
||||||
* If not specified, defaults to the system configuration e.g. `/etc/resolv.conf` on Unix. */
|
|
||||||
nameServer?: {
|
|
||||||
/** The IP address of the name server */
|
|
||||||
ipAddr: string;
|
|
||||||
/** The port number the query will be sent to.
|
|
||||||
* If not specified, defaults to 53. */
|
|
||||||
port?: number;
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
/** If `resolveDns` is called with "MX" record type specified, it will return an array of this interface. */
|
|
||||||
export interface MXRecord {
|
|
||||||
preference: number;
|
|
||||||
exchange: string;
|
|
||||||
}
|
|
||||||
|
|
||||||
/** If `resolveDns` is called with "SRV" record type specified, it will return an array of this interface. */
|
|
||||||
export interface SRVRecord {
|
|
||||||
priority: number;
|
|
||||||
weight: number;
|
|
||||||
port: number;
|
|
||||||
target: string;
|
|
||||||
}
|
|
||||||
|
|
||||||
export function resolveDns(
|
|
||||||
query: string,
|
|
||||||
recordType: "A" | "AAAA" | "ANAME" | "CNAME" | "PTR",
|
|
||||||
options?: ResolveDnsOptions,
|
|
||||||
): Promise<string[]>;
|
|
||||||
|
|
||||||
export function resolveDns(
|
|
||||||
query: string,
|
|
||||||
recordType: "MX",
|
|
||||||
options?: ResolveDnsOptions,
|
|
||||||
): Promise<MXRecord[]>;
|
|
||||||
|
|
||||||
export function resolveDns(
|
|
||||||
query: string,
|
|
||||||
recordType: "SRV",
|
|
||||||
options?: ResolveDnsOptions,
|
|
||||||
): Promise<SRVRecord[]>;
|
|
||||||
|
|
||||||
export function resolveDns(
|
|
||||||
query: string,
|
|
||||||
recordType: "TXT",
|
|
||||||
options?: ResolveDnsOptions,
|
|
||||||
): Promise<string[][]>;
|
|
||||||
|
|
||||||
/** ** UNSTABLE**: new API, yet to be vetted.
|
|
||||||
*
|
|
||||||
* Performs DNS resolution against the given query, returning resolved records.
|
|
||||||
* Fails in the cases such as:
|
|
||||||
* - the query is in invalid format
|
|
||||||
* - the options have an invalid parameter, e.g. `nameServer.port` is beyond the range of 16-bit unsigned integer
|
|
||||||
* - timed out
|
|
||||||
*
|
|
||||||
* ```ts
|
|
||||||
* const a = await Deno.resolveDns("example.com", "A");
|
|
||||||
*
|
|
||||||
* const aaaa = await Deno.resolveDns("example.com", "AAAA", {
|
|
||||||
* nameServer: { ipAddr: "8.8.8.8", port: 1234 },
|
|
||||||
* });
|
|
||||||
* ```
|
|
||||||
*
|
|
||||||
* Requires `allow-net` permission.
|
|
||||||
*/
|
|
||||||
export function resolveDns(
|
|
||||||
query: string,
|
|
||||||
recordType: RecordType,
|
|
||||||
options?: ResolveDnsOptions,
|
|
||||||
): Promise<string[] | MXRecord[] | SRVRecord[] | string[][]>;
|
|
||||||
|
|
||||||
/** **UNSTABLE**: new API, yet to be vetted.
|
|
||||||
*
|
|
||||||
* A generic transport listener for message-oriented protocols. */
|
|
||||||
export interface DatagramConn extends AsyncIterable<[Uint8Array, Addr]> {
|
|
||||||
/** **UNSTABLE**: new API, yet to be vetted.
|
|
||||||
*
|
|
||||||
* Waits for and resolves to the next message to the `UDPConn`. */
|
|
||||||
receive(p?: Uint8Array): Promise<[Uint8Array, Addr]>;
|
|
||||||
/** UNSTABLE: new API, yet to be vetted.
|
|
||||||
*
|
|
||||||
* Sends a message to the target. */
|
|
||||||
send(p: Uint8Array, addr: Addr): Promise<number>;
|
|
||||||
/** UNSTABLE: new API, yet to be vetted.
|
|
||||||
*
|
|
||||||
* Close closes the socket. Any pending message promises will be rejected
|
|
||||||
* with errors. */
|
|
||||||
close(): void;
|
|
||||||
/** Return the address of the `UDPConn`. */
|
|
||||||
readonly addr: Addr;
|
|
||||||
[Symbol.asyncIterator](): AsyncIterableIterator<[Uint8Array, Addr]>;
|
|
||||||
}
|
|
||||||
|
|
||||||
export interface UnixListenOptions {
|
|
||||||
/** A Path to the Unix Socket. */
|
|
||||||
path: string;
|
|
||||||
}
|
|
||||||
|
|
||||||
/** **UNSTABLE**: new API, yet to be vetted.
|
|
||||||
*
|
|
||||||
* Listen announces on the local transport address.
|
|
||||||
*
|
|
||||||
* ```ts
|
|
||||||
* const listener = Deno.listen({ path: "/foo/bar.sock", transport: "unix" })
|
|
||||||
* ```
|
|
||||||
*
|
|
||||||
* Requires `allow-read` and `allow-write` permission. */
|
|
||||||
export function listen(
|
|
||||||
options: UnixListenOptions & { transport: "unix" },
|
|
||||||
): Listener;
|
|
||||||
|
|
||||||
/** **UNSTABLE**: new API, yet to be vetted
|
|
||||||
*
|
|
||||||
* Listen announces on the local transport address.
|
|
||||||
*
|
|
||||||
* ```ts
|
|
||||||
* const listener1 = Deno.listenDatagram({
|
|
||||||
* port: 80,
|
|
||||||
* transport: "udp"
|
|
||||||
* });
|
|
||||||
* const listener2 = Deno.listenDatagram({
|
|
||||||
* hostname: "golang.org",
|
|
||||||
* port: 80,
|
|
||||||
* transport: "udp"
|
|
||||||
* });
|
|
||||||
* ```
|
|
||||||
*
|
|
||||||
* Requires `allow-net` permission. */
|
|
||||||
export function listenDatagram(
|
|
||||||
options: ListenOptions & { transport: "udp" },
|
|
||||||
): DatagramConn;
|
|
||||||
|
|
||||||
/** **UNSTABLE**: new API, yet to be vetted
|
|
||||||
*
|
|
||||||
* Listen announces on the local transport address.
|
|
||||||
*
|
|
||||||
* ```ts
|
|
||||||
* const listener = Deno.listenDatagram({
|
|
||||||
* path: "/foo/bar.sock",
|
|
||||||
* transport: "unixpacket"
|
|
||||||
* });
|
|
||||||
* ```
|
|
||||||
*
|
|
||||||
* Requires `allow-read` and `allow-write` permission. */
|
|
||||||
export function listenDatagram(
|
|
||||||
options: UnixListenOptions & { transport: "unixpacket" },
|
|
||||||
): DatagramConn;
|
|
||||||
|
|
||||||
export interface UnixConnectOptions {
|
|
||||||
transport: "unix";
|
|
||||||
path: string;
|
|
||||||
}
|
|
||||||
|
|
||||||
/** **UNSTABLE**: The unix socket transport is unstable as a new API yet to
|
|
||||||
* be vetted. The TCP transport is considered stable.
|
|
||||||
*
|
|
||||||
* Connects to the hostname (default is "127.0.0.1") and port on the named
|
|
||||||
* transport (default is "tcp"), and resolves to the connection (`Conn`).
|
|
||||||
*
|
|
||||||
* ```ts
|
|
||||||
* const conn1 = await Deno.connect({ port: 80 });
|
|
||||||
* const conn2 = await Deno.connect({ hostname: "192.0.2.1", port: 80 });
|
|
||||||
* const conn3 = await Deno.connect({ hostname: "[2001:db8::1]", port: 80 });
|
|
||||||
* const conn4 = await Deno.connect({ hostname: "golang.org", port: 80, transport: "tcp" });
|
|
||||||
* const conn5 = await Deno.connect({ path: "/foo/bar.sock", transport: "unix" });
|
|
||||||
* ```
|
|
||||||
*
|
|
||||||
* Requires `allow-net` permission for "tcp" and `allow-read` for "unix". */
|
|
||||||
export function connect(
|
|
||||||
options: ConnectOptions | UnixConnectOptions,
|
|
||||||
): Promise<Conn>;
|
|
||||||
|
|
||||||
export interface StartTlsOptions {
|
|
||||||
/** A literal IP address or host name that can be resolved to an IP address.
|
|
||||||
* If not specified, defaults to `127.0.0.1`. */
|
|
||||||
hostname?: string;
|
|
||||||
/** Server certificate file. */
|
|
||||||
certFile?: string;
|
|
||||||
}
|
|
||||||
|
|
||||||
/** **UNSTABLE**: new API, yet to be vetted.
|
|
||||||
*
|
|
||||||
* Start TLS handshake from an existing connection using
|
|
||||||
* an optional cert file, hostname (default is "127.0.0.1"). The
|
|
||||||
* cert file is optional and if not included Mozilla's root certificates will
|
|
||||||
* be used (see also https://github.com/ctz/webpki-roots for specifics)
|
|
||||||
* Using this function requires that the other end of the connection is
|
|
||||||
* prepared for TLS handshake.
|
|
||||||
*
|
|
||||||
* ```ts
|
|
||||||
* const conn = await Deno.connect({ port: 80, hostname: "127.0.0.1" });
|
|
||||||
* const tlsConn = await Deno.startTls(conn, { certFile: "./certs/my_custom_root_CA.pem", hostname: "localhost" });
|
|
||||||
* ```
|
|
||||||
*
|
|
||||||
* Requires `allow-net` permission.
|
|
||||||
*/
|
|
||||||
export function startTls(
|
|
||||||
conn: Conn,
|
|
||||||
options?: StartTlsOptions,
|
|
||||||
): Promise<Conn>;
|
|
||||||
|
|
||||||
export interface ListenTlsOptions {
|
|
||||||
/** **UNSTABLE**: new API, yet to be vetted.
|
|
||||||
*
|
|
||||||
* Application-Layer Protocol Negotiation (ALPN) protocols to announce to
|
|
||||||
* the client. If not specified, no ALPN extension will be included in the
|
|
||||||
* TLS handshake.
|
|
||||||
*/
|
|
||||||
alpnProtocols?: string[];
|
|
||||||
}
|
|
||||||
|
|
||||||
/** **UNSTABLE**: The `signo` argument may change to require the Deno.Signal
|
/** **UNSTABLE**: The `signo` argument may change to require the Deno.Signal
|
||||||
* enum.
|
* enum.
|
||||||
*
|
*
|
||||||
|
@ -1182,36 +957,6 @@ declare namespace Deno {
|
||||||
bytesReceived: number;
|
bytesReceived: number;
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface RequestEvent {
|
|
||||||
readonly request: Request;
|
|
||||||
respondWith(r: Response | Promise<Response>): Promise<void>;
|
|
||||||
}
|
|
||||||
|
|
||||||
export interface HttpConn extends AsyncIterable<RequestEvent> {
|
|
||||||
readonly rid: number;
|
|
||||||
|
|
||||||
nextRequest(): Promise<RequestEvent | null>;
|
|
||||||
close(): void;
|
|
||||||
}
|
|
||||||
|
|
||||||
/** **UNSTABLE**: new API, yet to be vetted.
|
|
||||||
*
|
|
||||||
* Services HTTP requests given a TCP or TLS socket.
|
|
||||||
*
|
|
||||||
* ```ts
|
|
||||||
* const conn = await Deno.connect({ port: 80, hostname: "127.0.0.1" });
|
|
||||||
* const httpConn = Deno.serveHttp(conn);
|
|
||||||
* const e = await httpConn.nextRequest();
|
|
||||||
* if (e) {
|
|
||||||
* e.respondWith(new Response("Hello World"));
|
|
||||||
* }
|
|
||||||
* ```
|
|
||||||
*
|
|
||||||
* If `httpConn.nextRequest()` encounters an error or returns `null`
|
|
||||||
* then the underlying HttpConn resource is closed automatically.
|
|
||||||
*/
|
|
||||||
export function serveHttp(conn: Conn): HttpConn;
|
|
||||||
|
|
||||||
/** **UNSTABLE**: New option, yet to be vetted. */
|
/** **UNSTABLE**: New option, yet to be vetted. */
|
||||||
export interface TestDefinition {
|
export interface TestDefinition {
|
||||||
/** Specifies the permissions that should be used to run the test.
|
/** Specifies the permissions that should be used to run the test.
|
||||||
|
|
|
@ -334,12 +334,14 @@ pub fn get_types(unstable: bool) -> String {
|
||||||
crate::tsc::DENO_WEBSTORAGE_LIB,
|
crate::tsc::DENO_WEBSTORAGE_LIB,
|
||||||
crate::tsc::DENO_CRYPTO_LIB,
|
crate::tsc::DENO_CRYPTO_LIB,
|
||||||
crate::tsc::DENO_BROADCAST_CHANNEL_LIB,
|
crate::tsc::DENO_BROADCAST_CHANNEL_LIB,
|
||||||
|
crate::tsc::DENO_NET_LIB,
|
||||||
crate::tsc::SHARED_GLOBALS_LIB,
|
crate::tsc::SHARED_GLOBALS_LIB,
|
||||||
crate::tsc::WINDOW_LIB,
|
crate::tsc::WINDOW_LIB,
|
||||||
];
|
];
|
||||||
|
|
||||||
if unstable {
|
if unstable {
|
||||||
types.push(crate::tsc::UNSTABLE_NS_LIB);
|
types.push(crate::tsc::UNSTABLE_NS_LIB);
|
||||||
|
types.push(crate::tsc::DENO_NET_UNSTABLE_LIB);
|
||||||
}
|
}
|
||||||
|
|
||||||
types.join("\n")
|
types.join("\n")
|
||||||
|
|
|
@ -2,9 +2,9 @@
|
||||||
|
|
||||||
use crate::itest;
|
use crate::itest;
|
||||||
use deno_core::url;
|
use deno_core::url;
|
||||||
use deno_runtime::ops::tls::rustls;
|
use deno_runtime::deno_net::ops_tls::rustls;
|
||||||
use deno_runtime::ops::tls::webpki;
|
use deno_runtime::deno_net::ops_tls::webpki;
|
||||||
use deno_runtime::ops::tls::TlsStream;
|
use deno_runtime::deno_net::ops_tls::TlsStream;
|
||||||
use std::fs;
|
use std::fs;
|
||||||
use std::io::BufReader;
|
use std::io::BufReader;
|
||||||
use std::io::Cursor;
|
use std::io::Cursor;
|
||||||
|
|
|
@ -44,6 +44,9 @@ pub static DENO_WEBSTORAGE_LIB: &str =
|
||||||
pub static DENO_CRYPTO_LIB: &str = include_str!(env!("DENO_CRYPTO_LIB_PATH"));
|
pub static DENO_CRYPTO_LIB: &str = include_str!(env!("DENO_CRYPTO_LIB_PATH"));
|
||||||
pub static DENO_BROADCAST_CHANNEL_LIB: &str =
|
pub static DENO_BROADCAST_CHANNEL_LIB: &str =
|
||||||
include_str!(env!("DENO_BROADCAST_CHANNEL_LIB_PATH"));
|
include_str!(env!("DENO_BROADCAST_CHANNEL_LIB_PATH"));
|
||||||
|
pub static DENO_NET_LIB: &str = include_str!(env!("DENO_NET_LIB_PATH"));
|
||||||
|
pub static DENO_NET_UNSTABLE_LIB: &str =
|
||||||
|
include_str!(env!("DENO_NET_UNSTABLE_LIB_PATH"));
|
||||||
pub static SHARED_GLOBALS_LIB: &str =
|
pub static SHARED_GLOBALS_LIB: &str =
|
||||||
include_str!("dts/lib.deno.shared_globals.d.ts");
|
include_str!("dts/lib.deno.shared_globals.d.ts");
|
||||||
pub static WINDOW_LIB: &str = include_str!("dts/lib.deno.window.d.ts");
|
pub static WINDOW_LIB: &str = include_str!("dts/lib.deno.window.d.ts");
|
||||||
|
|
19
core/core.js
19
core/core.js
|
@ -132,6 +132,23 @@
|
||||||
opSync("op_print", str, isErr);
|
opSync("op_print", str, isErr);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Some "extensions" rely on "BadResource" and "Interrupted" errors in the
|
||||||
|
// JS code (eg. "deno_net") so they are provided in "Deno.core" but later
|
||||||
|
// reexported on "Deno.errors"
|
||||||
|
class BadResource extends Error {
|
||||||
|
constructor(msg) {
|
||||||
|
super(msg);
|
||||||
|
this.name = "BadResource";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class Interrupted extends Error {
|
||||||
|
constructor(msg) {
|
||||||
|
super(msg);
|
||||||
|
this.name = "Interrupted";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Provide bootstrap namespace
|
// Provide bootstrap namespace
|
||||||
window.__bootstrap = {};
|
window.__bootstrap = {};
|
||||||
// Extra Deno.core.* exports
|
// Extra Deno.core.* exports
|
||||||
|
@ -146,5 +163,7 @@
|
||||||
registerErrorClass,
|
registerErrorClass,
|
||||||
handleAsyncMsgFromRust,
|
handleAsyncMsgFromRust,
|
||||||
syncOpsCache,
|
syncOpsCache,
|
||||||
|
BadResource,
|
||||||
|
Interrupted,
|
||||||
});
|
});
|
||||||
})(this);
|
})(this);
|
||||||
|
|
|
@ -3,11 +3,25 @@
|
||||||
|
|
||||||
((window) => {
|
((window) => {
|
||||||
const core = window.Deno.core;
|
const core = window.Deno.core;
|
||||||
const { errors } = window.__bootstrap.errors;
|
const { BadResource } = core;
|
||||||
const { read, write } = window.__bootstrap.io;
|
|
||||||
|
async function read(
|
||||||
|
rid,
|
||||||
|
buffer,
|
||||||
|
) {
|
||||||
|
if (buffer.length === 0) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
const nread = await core.opAsync("op_net_read_async", rid, buffer);
|
||||||
|
return nread === 0 ? null : nread;
|
||||||
|
}
|
||||||
|
|
||||||
|
async function write(rid, data) {
|
||||||
|
return await core.opAsync("op_net_write_async", rid, data);
|
||||||
|
}
|
||||||
|
|
||||||
function shutdown(rid) {
|
function shutdown(rid) {
|
||||||
return core.opAsync("op_shutdown", rid);
|
return core.opAsync("op_net_shutdown", rid);
|
||||||
}
|
}
|
||||||
|
|
||||||
function opAccept(rid, transport) {
|
function opAccept(rid, transport) {
|
||||||
|
@ -104,7 +118,7 @@
|
||||||
try {
|
try {
|
||||||
conn = await this.accept();
|
conn = await this.accept();
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
if (error instanceof errors.BadResource) {
|
if (error instanceof BadResource) {
|
||||||
return { value: undefined, done: true };
|
return { value: undefined, done: true };
|
||||||
}
|
}
|
||||||
throw error;
|
throw error;
|
||||||
|
@ -171,7 +185,7 @@
|
||||||
try {
|
try {
|
||||||
yield await this.receive();
|
yield await this.receive();
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
if (err instanceof errors.BadResource) {
|
if (err instanceof BadResource) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
throw err;
|
throw err;
|
|
@ -5,8 +5,8 @@
|
||||||
const { InnerBody } = window.__bootstrap.fetchBody;
|
const { InnerBody } = window.__bootstrap.fetchBody;
|
||||||
const { Response, fromInnerRequest, toInnerResponse, newInnerRequest } =
|
const { Response, fromInnerRequest, toInnerResponse, newInnerRequest } =
|
||||||
window.__bootstrap.fetch;
|
window.__bootstrap.fetch;
|
||||||
const errors = window.__bootstrap.errors.errors;
|
|
||||||
const core = window.Deno.core;
|
const core = window.Deno.core;
|
||||||
|
const { BadResource, Interrupted } = core;
|
||||||
const { ReadableStream } = window.__bootstrap.streams;
|
const { ReadableStream } = window.__bootstrap.streams;
|
||||||
const abortSignal = window.__bootstrap.abortSignal;
|
const abortSignal = window.__bootstrap.abortSignal;
|
||||||
|
|
||||||
|
@ -42,9 +42,9 @@
|
||||||
// a generic `BadResource` error. Instead store this error and replace
|
// a generic `BadResource` error. Instead store this error and replace
|
||||||
// those with it.
|
// those with it.
|
||||||
this[connErrorSymbol] = error;
|
this[connErrorSymbol] = error;
|
||||||
if (error instanceof errors.BadResource) {
|
if (error instanceof BadResource) {
|
||||||
return null;
|
return null;
|
||||||
} else if (error instanceof errors.Interrupted) {
|
} else if (error instanceof Interrupted) {
|
||||||
return null;
|
return null;
|
||||||
} else if (error.message.includes("connection closed")) {
|
} else if (error.message.includes("connection closed")) {
|
||||||
return null;
|
return null;
|
||||||
|
@ -159,7 +159,7 @@
|
||||||
], respBody instanceof Uint8Array ? respBody : null);
|
], respBody instanceof Uint8Array ? respBody : null);
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
const connError = httpConn[connErrorSymbol];
|
const connError = httpConn[connErrorSymbol];
|
||||||
if (error instanceof errors.BadResource && connError != null) {
|
if (error instanceof BadResource && connError != null) {
|
||||||
// deno-lint-ignore no-ex-assign
|
// deno-lint-ignore no-ex-assign
|
||||||
error = new connError.constructor(connError.message);
|
error = new connError.constructor(connError.message);
|
||||||
}
|
}
|
||||||
|
@ -192,7 +192,7 @@
|
||||||
);
|
);
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
const connError = httpConn[connErrorSymbol];
|
const connError = httpConn[connErrorSymbol];
|
||||||
if (error instanceof errors.BadResource && connError != null) {
|
if (error instanceof BadResource && connError != null) {
|
||||||
// deno-lint-ignore no-ex-assign
|
// deno-lint-ignore no-ex-assign
|
||||||
error = new connError.constructor(connError.message);
|
error = new connError.constructor(connError.message);
|
||||||
}
|
}
|
31
extensions/net/Cargo.toml
Normal file
31
extensions/net/Cargo.toml
Normal file
|
@ -0,0 +1,31 @@
|
||||||
|
# Copyright 2018-2021 the Deno authors. All rights reserved. MIT license.
|
||||||
|
|
||||||
|
[package]
|
||||||
|
name = "deno_net"
|
||||||
|
version = "0.1.0"
|
||||||
|
edition = "2018"
|
||||||
|
description = "Networking for Deno"
|
||||||
|
authors = ["the Deno authors"]
|
||||||
|
license = "MIT"
|
||||||
|
readme = "README.md"
|
||||||
|
repository = "https://github.com/denoland/deno"
|
||||||
|
|
||||||
|
[lib]
|
||||||
|
path = "lib.rs"
|
||||||
|
|
||||||
|
[dependencies]
|
||||||
|
deno_core = { version = "0.92.0", path = "../../core" }
|
||||||
|
|
||||||
|
bytes = "1"
|
||||||
|
log = "0.4.14"
|
||||||
|
lazy_static = "1.4.0"
|
||||||
|
http = "0.2.3"
|
||||||
|
hyper = { version = "0.14.9", features = ["server", "stream", "http1", "http2", "runtime"] }
|
||||||
|
rustls = "0.19.0"
|
||||||
|
serde = { version = "1.0.125", features = ["derive"] }
|
||||||
|
tokio = { version = "1.7.1", features = ["full"] }
|
||||||
|
tokio-util = { version = "0.6", features = ["io"] }
|
||||||
|
webpki = "0.21.4"
|
||||||
|
webpki-roots = "0.21.1"
|
||||||
|
trust-dns-proto = "0.20.3"
|
||||||
|
trust-dns-resolver = { version = "0.20.3", features = ["tokio-runtime", "serde-config"] }
|
30
extensions/net/README.md
Normal file
30
extensions/net/README.md
Normal file
|
@ -0,0 +1,30 @@
|
||||||
|
# deno_net
|
||||||
|
|
||||||
|
This crate implements networking APIs.
|
||||||
|
|
||||||
|
This crate depends on following extensions:
|
||||||
|
|
||||||
|
- "deno_web"
|
||||||
|
- "deno_fetch"
|
||||||
|
|
||||||
|
Following ops are provided:
|
||||||
|
|
||||||
|
- "op_net_read_async"
|
||||||
|
- "op_net_write_async"
|
||||||
|
- "op_net_shutdown"
|
||||||
|
- "op_accept"
|
||||||
|
- "op_connect"
|
||||||
|
- "op_listen"
|
||||||
|
- "op_datagram_receive"
|
||||||
|
- "op_datagram_send"
|
||||||
|
- "op_dns_resolve"
|
||||||
|
- "op_start_tls"
|
||||||
|
- "op_connect_tls"
|
||||||
|
- "op_listen_tls"
|
||||||
|
- "op_accept_tls"
|
||||||
|
- "op_http_start"
|
||||||
|
- "op_http_request_next"
|
||||||
|
- "op_http_request_read"
|
||||||
|
- "op_http_response"
|
||||||
|
- "op_http_response_write"
|
||||||
|
- "op_http_response_close"
|
232
extensions/net/io.rs
Normal file
232
extensions/net/io.rs
Normal file
|
@ -0,0 +1,232 @@
|
||||||
|
// Copyright 2018-2021 the Deno authors. All rights reserved. MIT license.
|
||||||
|
|
||||||
|
use crate::ops_tls as tls;
|
||||||
|
use deno_core::error::null_opbuf;
|
||||||
|
use deno_core::error::AnyError;
|
||||||
|
use deno_core::error::{bad_resource_id, not_supported};
|
||||||
|
use deno_core::op_async;
|
||||||
|
use deno_core::AsyncMutFuture;
|
||||||
|
use deno_core::AsyncRefCell;
|
||||||
|
use deno_core::CancelHandle;
|
||||||
|
use deno_core::CancelTryFuture;
|
||||||
|
use deno_core::OpPair;
|
||||||
|
use deno_core::OpState;
|
||||||
|
use deno_core::RcRef;
|
||||||
|
use deno_core::Resource;
|
||||||
|
use deno_core::ResourceId;
|
||||||
|
use deno_core::ZeroCopyBuf;
|
||||||
|
use std::borrow::Cow;
|
||||||
|
use std::cell::RefCell;
|
||||||
|
use std::rc::Rc;
|
||||||
|
use tokio::io::AsyncRead;
|
||||||
|
use tokio::io::AsyncReadExt;
|
||||||
|
use tokio::io::AsyncWrite;
|
||||||
|
use tokio::io::AsyncWriteExt;
|
||||||
|
use tokio::net::tcp;
|
||||||
|
|
||||||
|
#[cfg(unix)]
|
||||||
|
use tokio::net::unix;
|
||||||
|
|
||||||
|
pub fn init() -> Vec<OpPair> {
|
||||||
|
vec![
|
||||||
|
("op_net_read_async", op_async(op_read_async)),
|
||||||
|
("op_net_write_async", op_async(op_write_async)),
|
||||||
|
("op_net_shutdown", op_async(op_shutdown)),
|
||||||
|
]
|
||||||
|
}
|
||||||
|
|
||||||
|
/// A full duplex resource has a read and write ends that are completely
|
||||||
|
/// independent, like TCP/Unix sockets and TLS streams.
|
||||||
|
#[derive(Debug)]
|
||||||
|
pub struct FullDuplexResource<R, W> {
|
||||||
|
rd: AsyncRefCell<R>,
|
||||||
|
wr: AsyncRefCell<W>,
|
||||||
|
// When a full-duplex resource is closed, all pending 'read' ops are
|
||||||
|
// canceled, while 'write' ops are allowed to complete. Therefore only
|
||||||
|
// 'read' futures should be attached to this cancel handle.
|
||||||
|
cancel_handle: CancelHandle,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<R, W> FullDuplexResource<R, W>
|
||||||
|
where
|
||||||
|
R: AsyncRead + Unpin + 'static,
|
||||||
|
W: AsyncWrite + Unpin + 'static,
|
||||||
|
{
|
||||||
|
pub fn new((rd, wr): (R, W)) -> Self {
|
||||||
|
Self {
|
||||||
|
rd: rd.into(),
|
||||||
|
wr: wr.into(),
|
||||||
|
cancel_handle: Default::default(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn into_inner(self) -> (R, W) {
|
||||||
|
(self.rd.into_inner(), self.wr.into_inner())
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn rd_borrow_mut(self: &Rc<Self>) -> AsyncMutFuture<R> {
|
||||||
|
RcRef::map(self, |r| &r.rd).borrow_mut()
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn wr_borrow_mut(self: &Rc<Self>) -> AsyncMutFuture<W> {
|
||||||
|
RcRef::map(self, |r| &r.wr).borrow_mut()
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn cancel_handle(self: &Rc<Self>) -> RcRef<CancelHandle> {
|
||||||
|
RcRef::map(self, |r| &r.cancel_handle)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn cancel_read_ops(&self) {
|
||||||
|
self.cancel_handle.cancel()
|
||||||
|
}
|
||||||
|
|
||||||
|
pub async fn read(
|
||||||
|
self: &Rc<Self>,
|
||||||
|
buf: &mut [u8],
|
||||||
|
) -> Result<usize, AnyError> {
|
||||||
|
let mut rd = self.rd_borrow_mut().await;
|
||||||
|
let nread = rd.read(buf).try_or_cancel(self.cancel_handle()).await?;
|
||||||
|
Ok(nread)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub async fn write(self: &Rc<Self>, buf: &[u8]) -> Result<usize, AnyError> {
|
||||||
|
let mut wr = self.wr_borrow_mut().await;
|
||||||
|
let nwritten = wr.write(buf).await?;
|
||||||
|
Ok(nwritten)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub async fn shutdown(self: &Rc<Self>) -> Result<(), AnyError> {
|
||||||
|
let mut wr = self.wr_borrow_mut().await;
|
||||||
|
wr.shutdown().await?;
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub type TcpStreamResource =
|
||||||
|
FullDuplexResource<tcp::OwnedReadHalf, tcp::OwnedWriteHalf>;
|
||||||
|
|
||||||
|
impl Resource for TcpStreamResource {
|
||||||
|
fn name(&self) -> Cow<str> {
|
||||||
|
"tcpStream".into()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn close(self: Rc<Self>) {
|
||||||
|
self.cancel_read_ops();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub type TlsStreamResource = FullDuplexResource<tls::ReadHalf, tls::WriteHalf>;
|
||||||
|
|
||||||
|
impl Resource for TlsStreamResource {
|
||||||
|
fn name(&self) -> Cow<str> {
|
||||||
|
"tlsStream".into()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn close(self: Rc<Self>) {
|
||||||
|
self.cancel_read_ops();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(unix)]
|
||||||
|
pub type UnixStreamResource =
|
||||||
|
FullDuplexResource<unix::OwnedReadHalf, unix::OwnedWriteHalf>;
|
||||||
|
|
||||||
|
#[cfg(not(unix))]
|
||||||
|
pub struct UnixStreamResource;
|
||||||
|
|
||||||
|
#[cfg(not(unix))]
|
||||||
|
impl UnixStreamResource {
|
||||||
|
pub async fn read(
|
||||||
|
self: &Rc<Self>,
|
||||||
|
_buf: &mut [u8],
|
||||||
|
) -> Result<usize, AnyError> {
|
||||||
|
unreachable!()
|
||||||
|
}
|
||||||
|
pub async fn write(self: &Rc<Self>, _buf: &[u8]) -> Result<usize, AnyError> {
|
||||||
|
unreachable!()
|
||||||
|
}
|
||||||
|
pub async fn shutdown(self: &Rc<Self>) -> Result<(), AnyError> {
|
||||||
|
unreachable!()
|
||||||
|
}
|
||||||
|
pub fn cancel_read_ops(&self) {
|
||||||
|
unreachable!()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Resource for UnixStreamResource {
|
||||||
|
fn name(&self) -> Cow<str> {
|
||||||
|
"unixStream".into()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn close(self: Rc<Self>) {
|
||||||
|
self.cancel_read_ops();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
async fn op_read_async(
|
||||||
|
state: Rc<RefCell<OpState>>,
|
||||||
|
rid: ResourceId,
|
||||||
|
buf: Option<ZeroCopyBuf>,
|
||||||
|
) -> Result<u32, AnyError> {
|
||||||
|
let buf = &mut buf.ok_or_else(null_opbuf)?;
|
||||||
|
let resource = state
|
||||||
|
.borrow()
|
||||||
|
.resource_table
|
||||||
|
.get_any(rid)
|
||||||
|
.ok_or_else(bad_resource_id)?;
|
||||||
|
let nread = if let Some(s) = resource.downcast_rc::<TcpStreamResource>() {
|
||||||
|
s.read(buf).await?
|
||||||
|
} else if let Some(s) = resource.downcast_rc::<TlsStreamResource>() {
|
||||||
|
s.read(buf).await?
|
||||||
|
} else if let Some(s) = resource.downcast_rc::<UnixStreamResource>() {
|
||||||
|
s.read(buf).await?
|
||||||
|
} else {
|
||||||
|
return Err(not_supported());
|
||||||
|
};
|
||||||
|
Ok(nread as u32)
|
||||||
|
}
|
||||||
|
|
||||||
|
async fn op_write_async(
|
||||||
|
state: Rc<RefCell<OpState>>,
|
||||||
|
rid: ResourceId,
|
||||||
|
buf: Option<ZeroCopyBuf>,
|
||||||
|
) -> Result<u32, AnyError> {
|
||||||
|
let buf = &buf.ok_or_else(null_opbuf)?;
|
||||||
|
let resource = state
|
||||||
|
.borrow()
|
||||||
|
.resource_table
|
||||||
|
.get_any(rid)
|
||||||
|
.ok_or_else(bad_resource_id)?;
|
||||||
|
let nwritten = if let Some(s) = resource.downcast_rc::<TcpStreamResource>() {
|
||||||
|
s.write(buf).await?
|
||||||
|
} else if let Some(s) = resource.downcast_rc::<TlsStreamResource>() {
|
||||||
|
s.write(buf).await?
|
||||||
|
} else if let Some(s) = resource.downcast_rc::<UnixStreamResource>() {
|
||||||
|
s.write(buf).await?
|
||||||
|
} else {
|
||||||
|
return Err(not_supported());
|
||||||
|
};
|
||||||
|
Ok(nwritten as u32)
|
||||||
|
}
|
||||||
|
|
||||||
|
async fn op_shutdown(
|
||||||
|
state: Rc<RefCell<OpState>>,
|
||||||
|
rid: ResourceId,
|
||||||
|
_: (),
|
||||||
|
) -> Result<(), AnyError> {
|
||||||
|
let resource = state
|
||||||
|
.borrow()
|
||||||
|
.resource_table
|
||||||
|
.get_any(rid)
|
||||||
|
.ok_or_else(bad_resource_id)?;
|
||||||
|
if let Some(s) = resource.downcast_rc::<TcpStreamResource>() {
|
||||||
|
s.shutdown().await?;
|
||||||
|
} else if let Some(s) = resource.downcast_rc::<TlsStreamResource>() {
|
||||||
|
s.shutdown().await?;
|
||||||
|
} else if let Some(s) = resource.downcast_rc::<UnixStreamResource>() {
|
||||||
|
s.shutdown().await?;
|
||||||
|
} else {
|
||||||
|
return Err(not_supported());
|
||||||
|
}
|
||||||
|
Ok(())
|
||||||
|
}
|
149
extensions/net/lib.deno_net.d.ts
vendored
Normal file
149
extensions/net/lib.deno_net.d.ts
vendored
Normal file
|
@ -0,0 +1,149 @@
|
||||||
|
// Copyright 2018-2021 the Deno authors. All rights reserved. MIT license.
|
||||||
|
|
||||||
|
/// <reference no-default-lib="true" />
|
||||||
|
/// <reference lib="esnext" />
|
||||||
|
|
||||||
|
declare namespace Deno {
|
||||||
|
export interface NetAddr {
|
||||||
|
transport: "tcp" | "udp";
|
||||||
|
hostname: string;
|
||||||
|
port: number;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface UnixAddr {
|
||||||
|
transport: "unix" | "unixpacket";
|
||||||
|
path: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
export type Addr = NetAddr | UnixAddr;
|
||||||
|
|
||||||
|
/** A generic network listener for stream-oriented protocols. */
|
||||||
|
export interface Listener extends AsyncIterable<Conn> {
|
||||||
|
/** Waits for and resolves to the next connection to the `Listener`. */
|
||||||
|
accept(): Promise<Conn>;
|
||||||
|
/** Close closes the listener. Any pending accept promises will be rejected
|
||||||
|
* with errors. */
|
||||||
|
close(): void;
|
||||||
|
/** Return the address of the `Listener`. */
|
||||||
|
readonly addr: Addr;
|
||||||
|
|
||||||
|
/** Return the rid of the `Listener`. */
|
||||||
|
readonly rid: number;
|
||||||
|
|
||||||
|
[Symbol.asyncIterator](): AsyncIterableIterator<Conn>;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface Conn extends Reader, Writer, Closer {
|
||||||
|
/** The local address of the connection. */
|
||||||
|
readonly localAddr: Addr;
|
||||||
|
/** The remote address of the connection. */
|
||||||
|
readonly remoteAddr: Addr;
|
||||||
|
/** The resource ID of the connection. */
|
||||||
|
readonly rid: number;
|
||||||
|
/** Shuts down (`shutdown(2)`) the write side of the connection. Most
|
||||||
|
* callers should just use `close()`. */
|
||||||
|
closeWrite(): Promise<void>;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface ListenOptions {
|
||||||
|
/** The port to listen on. */
|
||||||
|
port: number;
|
||||||
|
/** A literal IP address or host name that can be resolved to an IP address.
|
||||||
|
* If not specified, defaults to `0.0.0.0`. */
|
||||||
|
hostname?: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Listen announces on the local transport address.
|
||||||
|
*
|
||||||
|
* ```ts
|
||||||
|
* const listener1 = Deno.listen({ port: 80 })
|
||||||
|
* const listener2 = Deno.listen({ hostname: "192.0.2.1", port: 80 })
|
||||||
|
* const listener3 = Deno.listen({ hostname: "[2001:db8::1]", port: 80 });
|
||||||
|
* const listener4 = Deno.listen({ hostname: "golang.org", port: 80, transport: "tcp" });
|
||||||
|
* ```
|
||||||
|
*
|
||||||
|
* Requires `allow-net` permission. */
|
||||||
|
export function listen(
|
||||||
|
options: ListenOptions & { transport?: "tcp" },
|
||||||
|
): Listener;
|
||||||
|
|
||||||
|
export interface ListenTlsOptions extends ListenOptions {
|
||||||
|
/** Server certificate file. */
|
||||||
|
certFile: string;
|
||||||
|
/** Server public key file. */
|
||||||
|
keyFile: string;
|
||||||
|
|
||||||
|
transport?: "tcp";
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Listen announces on the local transport address over TLS (transport layer
|
||||||
|
* security).
|
||||||
|
*
|
||||||
|
* ```ts
|
||||||
|
* const lstnr = Deno.listenTls({ port: 443, certFile: "./server.crt", keyFile: "./server.key" });
|
||||||
|
* ```
|
||||||
|
*
|
||||||
|
* Requires `allow-net` permission. */
|
||||||
|
export function listenTls(options: ListenTlsOptions): Listener;
|
||||||
|
|
||||||
|
export interface ConnectOptions {
|
||||||
|
/** The port to connect to. */
|
||||||
|
port: number;
|
||||||
|
/** A literal IP address or host name that can be resolved to an IP address.
|
||||||
|
* If not specified, defaults to `127.0.0.1`. */
|
||||||
|
hostname?: string;
|
||||||
|
transport?: "tcp";
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Connects to the hostname (default is "127.0.0.1") and port on the named
|
||||||
|
* transport (default is "tcp"), and resolves to the connection (`Conn`).
|
||||||
|
*
|
||||||
|
* ```ts
|
||||||
|
* const conn1 = await Deno.connect({ port: 80 });
|
||||||
|
* const conn2 = await Deno.connect({ hostname: "192.0.2.1", port: 80 });
|
||||||
|
* const conn3 = await Deno.connect({ hostname: "[2001:db8::1]", port: 80 });
|
||||||
|
* const conn4 = await Deno.connect({ hostname: "golang.org", port: 80, transport: "tcp" });
|
||||||
|
* ```
|
||||||
|
*
|
||||||
|
* Requires `allow-net` permission for "tcp". */
|
||||||
|
export function connect(options: ConnectOptions): Promise<Conn>;
|
||||||
|
|
||||||
|
export interface ConnectTlsOptions {
|
||||||
|
/** The port to connect to. */
|
||||||
|
port: number;
|
||||||
|
/** A literal IP address or host name that can be resolved to an IP address.
|
||||||
|
* If not specified, defaults to `127.0.0.1`. */
|
||||||
|
hostname?: string;
|
||||||
|
/** Server certificate file. */
|
||||||
|
certFile?: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Establishes a secure connection over TLS (transport layer security) using
|
||||||
|
* an optional cert file, hostname (default is "127.0.0.1") and port. The
|
||||||
|
* cert file is optional and if not included Mozilla's root certificates will
|
||||||
|
* be used (see also https://github.com/ctz/webpki-roots for specifics)
|
||||||
|
*
|
||||||
|
* ```ts
|
||||||
|
* const conn1 = await Deno.connectTls({ port: 80 });
|
||||||
|
* const conn2 = await Deno.connectTls({ certFile: "./certs/my_custom_root_CA.pem", hostname: "192.0.2.1", port: 80 });
|
||||||
|
* const conn3 = await Deno.connectTls({ hostname: "[2001:db8::1]", port: 80 });
|
||||||
|
* const conn4 = await Deno.connectTls({ certFile: "./certs/my_custom_root_CA.pem", hostname: "golang.org", port: 80});
|
||||||
|
* ```
|
||||||
|
*
|
||||||
|
* Requires `allow-net` permission.
|
||||||
|
*/
|
||||||
|
export function connectTls(options: ConnectTlsOptions): Promise<Conn>;
|
||||||
|
|
||||||
|
/** Shutdown socket send operations.
|
||||||
|
*
|
||||||
|
* Matches behavior of POSIX shutdown(3).
|
||||||
|
*
|
||||||
|
* ```ts
|
||||||
|
* const listener = Deno.listen({ port: 80 });
|
||||||
|
* const conn = await listener.accept();
|
||||||
|
* Deno.shutdown(conn.rid);
|
||||||
|
* ```
|
||||||
|
*/
|
||||||
|
export function shutdown(rid: number): Promise<void>;
|
||||||
|
}
|
262
extensions/net/lib.deno_net.unstable.d.ts
vendored
Normal file
262
extensions/net/lib.deno_net.unstable.d.ts
vendored
Normal file
|
@ -0,0 +1,262 @@
|
||||||
|
// Copyright 2018-2021 the Deno authors. All rights reserved. MIT license.
|
||||||
|
|
||||||
|
/// <reference no-default-lib="true" />
|
||||||
|
/// <reference lib="esnext" />
|
||||||
|
|
||||||
|
declare namespace Deno {
|
||||||
|
/** The type of the resource record.
|
||||||
|
* Only the listed types are supported currently. */
|
||||||
|
export type RecordType =
|
||||||
|
| "A"
|
||||||
|
| "AAAA"
|
||||||
|
| "ANAME"
|
||||||
|
| "CNAME"
|
||||||
|
| "MX"
|
||||||
|
| "PTR"
|
||||||
|
| "SRV"
|
||||||
|
| "TXT";
|
||||||
|
|
||||||
|
export interface ResolveDnsOptions {
|
||||||
|
/** The name server to be used for lookups.
|
||||||
|
* If not specified, defaults to the system configuration e.g. `/etc/resolv.conf` on Unix. */
|
||||||
|
nameServer?: {
|
||||||
|
/** The IP address of the name server */
|
||||||
|
ipAddr: string;
|
||||||
|
/** The port number the query will be sent to.
|
||||||
|
* If not specified, defaults to 53. */
|
||||||
|
port?: number;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
/** If `resolveDns` is called with "MX" record type specified, it will return an array of this interface. */
|
||||||
|
export interface MXRecord {
|
||||||
|
preference: number;
|
||||||
|
exchange: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** If `resolveDns` is called with "SRV" record type specified, it will return an array of this interface. */
|
||||||
|
export interface SRVRecord {
|
||||||
|
priority: number;
|
||||||
|
weight: number;
|
||||||
|
port: number;
|
||||||
|
target: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
export function resolveDns(
|
||||||
|
query: string,
|
||||||
|
recordType: "A" | "AAAA" | "ANAME" | "CNAME" | "PTR",
|
||||||
|
options?: ResolveDnsOptions,
|
||||||
|
): Promise<string[]>;
|
||||||
|
|
||||||
|
export function resolveDns(
|
||||||
|
query: string,
|
||||||
|
recordType: "MX",
|
||||||
|
options?: ResolveDnsOptions,
|
||||||
|
): Promise<MXRecord[]>;
|
||||||
|
|
||||||
|
export function resolveDns(
|
||||||
|
query: string,
|
||||||
|
recordType: "SRV",
|
||||||
|
options?: ResolveDnsOptions,
|
||||||
|
): Promise<SRVRecord[]>;
|
||||||
|
|
||||||
|
export function resolveDns(
|
||||||
|
query: string,
|
||||||
|
recordType: "TXT",
|
||||||
|
options?: ResolveDnsOptions,
|
||||||
|
): Promise<string[][]>;
|
||||||
|
|
||||||
|
/** ** UNSTABLE**: new API, yet to be vetted.
|
||||||
|
*
|
||||||
|
* Performs DNS resolution against the given query, returning resolved records.
|
||||||
|
* Fails in the cases such as:
|
||||||
|
* - the query is in invalid format
|
||||||
|
* - the options have an invalid parameter, e.g. `nameServer.port` is beyond the range of 16-bit unsigned integer
|
||||||
|
* - timed out
|
||||||
|
*
|
||||||
|
* ```ts
|
||||||
|
* const a = await Deno.resolveDns("example.com", "A");
|
||||||
|
*
|
||||||
|
* const aaaa = await Deno.resolveDns("example.com", "AAAA", {
|
||||||
|
* nameServer: { ipAddr: "8.8.8.8", port: 1234 },
|
||||||
|
* });
|
||||||
|
* ```
|
||||||
|
*
|
||||||
|
* Requires `allow-net` permission.
|
||||||
|
*/
|
||||||
|
export function resolveDns(
|
||||||
|
query: string,
|
||||||
|
recordType: RecordType,
|
||||||
|
options?: ResolveDnsOptions,
|
||||||
|
): Promise<string[] | MXRecord[] | SRVRecord[] | string[][]>;
|
||||||
|
|
||||||
|
/** **UNSTABLE**: new API, yet to be vetted.
|
||||||
|
*
|
||||||
|
* A generic transport listener for message-oriented protocols. */
|
||||||
|
export interface DatagramConn extends AsyncIterable<[Uint8Array, Addr]> {
|
||||||
|
/** **UNSTABLE**: new API, yet to be vetted.
|
||||||
|
*
|
||||||
|
* Waits for and resolves to the next message to the `UDPConn`. */
|
||||||
|
receive(p?: Uint8Array): Promise<[Uint8Array, Addr]>;
|
||||||
|
/** UNSTABLE: new API, yet to be vetted.
|
||||||
|
*
|
||||||
|
* Sends a message to the target. */
|
||||||
|
send(p: Uint8Array, addr: Addr): Promise<number>;
|
||||||
|
/** UNSTABLE: new API, yet to be vetted.
|
||||||
|
*
|
||||||
|
* Close closes the socket. Any pending message promises will be rejected
|
||||||
|
* with errors. */
|
||||||
|
close(): void;
|
||||||
|
/** Return the address of the `UDPConn`. */
|
||||||
|
readonly addr: Addr;
|
||||||
|
[Symbol.asyncIterator](): AsyncIterableIterator<[Uint8Array, Addr]>;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface UnixListenOptions {
|
||||||
|
/** A Path to the Unix Socket. */
|
||||||
|
path: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** **UNSTABLE**: new API, yet to be vetted.
|
||||||
|
*
|
||||||
|
* Listen announces on the local transport address.
|
||||||
|
*
|
||||||
|
* ```ts
|
||||||
|
* const listener = Deno.listen({ path: "/foo/bar.sock", transport: "unix" })
|
||||||
|
* ```
|
||||||
|
*
|
||||||
|
* Requires `allow-read` and `allow-write` permission. */
|
||||||
|
export function listen(
|
||||||
|
options: UnixListenOptions & { transport: "unix" },
|
||||||
|
): Listener;
|
||||||
|
|
||||||
|
/** **UNSTABLE**: new API, yet to be vetted
|
||||||
|
*
|
||||||
|
* Listen announces on the local transport address.
|
||||||
|
*
|
||||||
|
* ```ts
|
||||||
|
* const listener1 = Deno.listenDatagram({
|
||||||
|
* port: 80,
|
||||||
|
* transport: "udp"
|
||||||
|
* });
|
||||||
|
* const listener2 = Deno.listenDatagram({
|
||||||
|
* hostname: "golang.org",
|
||||||
|
* port: 80,
|
||||||
|
* transport: "udp"
|
||||||
|
* });
|
||||||
|
* ```
|
||||||
|
*
|
||||||
|
* Requires `allow-net` permission. */
|
||||||
|
export function listenDatagram(
|
||||||
|
options: ListenOptions & { transport: "udp" },
|
||||||
|
): DatagramConn;
|
||||||
|
|
||||||
|
/** **UNSTABLE**: new API, yet to be vetted
|
||||||
|
*
|
||||||
|
* Listen announces on the local transport address.
|
||||||
|
*
|
||||||
|
* ```ts
|
||||||
|
* const listener = Deno.listenDatagram({
|
||||||
|
* path: "/foo/bar.sock",
|
||||||
|
* transport: "unixpacket"
|
||||||
|
* });
|
||||||
|
* ```
|
||||||
|
*
|
||||||
|
* Requires `allow-read` and `allow-write` permission. */
|
||||||
|
export function listenDatagram(
|
||||||
|
options: UnixListenOptions & { transport: "unixpacket" },
|
||||||
|
): DatagramConn;
|
||||||
|
|
||||||
|
export interface UnixConnectOptions {
|
||||||
|
transport: "unix";
|
||||||
|
path: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** **UNSTABLE**: The unix socket transport is unstable as a new API yet to
|
||||||
|
* be vetted. The TCP transport is considered stable.
|
||||||
|
*
|
||||||
|
* Connects to the hostname (default is "127.0.0.1") and port on the named
|
||||||
|
* transport (default is "tcp"), and resolves to the connection (`Conn`).
|
||||||
|
*
|
||||||
|
* ```ts
|
||||||
|
* const conn1 = await Deno.connect({ port: 80 });
|
||||||
|
* const conn2 = await Deno.connect({ hostname: "192.0.2.1", port: 80 });
|
||||||
|
* const conn3 = await Deno.connect({ hostname: "[2001:db8::1]", port: 80 });
|
||||||
|
* const conn4 = await Deno.connect({ hostname: "golang.org", port: 80, transport: "tcp" });
|
||||||
|
* const conn5 = await Deno.connect({ path: "/foo/bar.sock", transport: "unix" });
|
||||||
|
* ```
|
||||||
|
*
|
||||||
|
* Requires `allow-net` permission for "tcp" and `allow-read` for "unix". */
|
||||||
|
export function connect(
|
||||||
|
options: ConnectOptions | UnixConnectOptions,
|
||||||
|
): Promise<Conn>;
|
||||||
|
|
||||||
|
export interface StartTlsOptions {
|
||||||
|
/** A literal IP address or host name that can be resolved to an IP address.
|
||||||
|
* If not specified, defaults to `127.0.0.1`. */
|
||||||
|
hostname?: string;
|
||||||
|
/** Server certificate file. */
|
||||||
|
certFile?: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** **UNSTABLE**: new API, yet to be vetted.
|
||||||
|
*
|
||||||
|
* Start TLS handshake from an existing connection using
|
||||||
|
* an optional cert file, hostname (default is "127.0.0.1"). The
|
||||||
|
* cert file is optional and if not included Mozilla's root certificates will
|
||||||
|
* be used (see also https://github.com/ctz/webpki-roots for specifics)
|
||||||
|
* Using this function requires that the other end of the connection is
|
||||||
|
* prepared for TLS handshake.
|
||||||
|
*
|
||||||
|
* ```ts
|
||||||
|
* const conn = await Deno.connect({ port: 80, hostname: "127.0.0.1" });
|
||||||
|
* const tlsConn = await Deno.startTls(conn, { certFile: "./certs/my_custom_root_CA.pem", hostname: "localhost" });
|
||||||
|
* ```
|
||||||
|
*
|
||||||
|
* Requires `allow-net` permission.
|
||||||
|
*/
|
||||||
|
export function startTls(
|
||||||
|
conn: Conn,
|
||||||
|
options?: StartTlsOptions,
|
||||||
|
): Promise<Conn>;
|
||||||
|
|
||||||
|
export interface ListenTlsOptions {
|
||||||
|
/** **UNSTABLE**: new API, yet to be vetted.
|
||||||
|
*
|
||||||
|
* Application-Layer Protocol Negotiation (ALPN) protocols to announce to
|
||||||
|
* the client. If not specified, no ALPN extension will be included in the
|
||||||
|
* TLS handshake.
|
||||||
|
*/
|
||||||
|
alpnProtocols?: string[];
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface RequestEvent {
|
||||||
|
readonly request: Request;
|
||||||
|
respondWith(r: Response | Promise<Response>): Promise<void>;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface HttpConn extends AsyncIterable<RequestEvent> {
|
||||||
|
readonly rid: number;
|
||||||
|
|
||||||
|
nextRequest(): Promise<RequestEvent | null>;
|
||||||
|
close(): void;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** **UNSTABLE**: new API, yet to be vetted.
|
||||||
|
*
|
||||||
|
* Services HTTP requests given a TCP or TLS socket.
|
||||||
|
*
|
||||||
|
* ```ts
|
||||||
|
* const conn = await Deno.connect({ port: 80, hostname: "127.0.0.1" });
|
||||||
|
* const httpConn = Deno.serveHttp(conn);
|
||||||
|
* const e = await httpConn.nextRequest();
|
||||||
|
* if (e) {
|
||||||
|
* e.respondWith(new Response("Hello World"));
|
||||||
|
* }
|
||||||
|
* ```
|
||||||
|
*
|
||||||
|
* If `httpConn.nextRequest()` encounters an error or returns `null`
|
||||||
|
* then the underlying HttpConn resource is closed automatically.
|
||||||
|
*/
|
||||||
|
export function serveHttp(conn: Conn): HttpConn;
|
||||||
|
}
|
113
extensions/net/lib.rs
Normal file
113
extensions/net/lib.rs
Normal file
|
@ -0,0 +1,113 @@
|
||||||
|
// Copyright 2018-2021 the Deno authors. All rights reserved. MIT license.
|
||||||
|
|
||||||
|
pub mod io;
|
||||||
|
pub mod ops;
|
||||||
|
pub mod ops_http;
|
||||||
|
pub mod ops_tls;
|
||||||
|
#[cfg(unix)]
|
||||||
|
pub mod ops_unix;
|
||||||
|
pub mod resolve_addr;
|
||||||
|
|
||||||
|
use deno_core::error::AnyError;
|
||||||
|
use deno_core::include_js_files;
|
||||||
|
use deno_core::Extension;
|
||||||
|
use deno_core::OpState;
|
||||||
|
use std::cell::RefCell;
|
||||||
|
use std::path::Path;
|
||||||
|
use std::path::PathBuf;
|
||||||
|
use std::rc::Rc;
|
||||||
|
|
||||||
|
pub trait NetPermissions {
|
||||||
|
fn check_net<T: AsRef<str>>(
|
||||||
|
&mut self,
|
||||||
|
_host: &(T, Option<u16>),
|
||||||
|
) -> Result<(), AnyError>;
|
||||||
|
fn check_read(&mut self, _p: &Path) -> Result<(), AnyError>;
|
||||||
|
fn check_write(&mut self, _p: &Path) -> Result<(), AnyError>;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// For use with this crate when the user does not want permission checks.
|
||||||
|
pub struct NoNetPermissions;
|
||||||
|
|
||||||
|
impl NetPermissions for NoNetPermissions {
|
||||||
|
fn check_net<T: AsRef<str>>(
|
||||||
|
&mut self,
|
||||||
|
_host: &(T, Option<u16>),
|
||||||
|
) -> Result<(), AnyError> {
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
fn check_read(&mut self, _p: &Path) -> Result<(), AnyError> {
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
fn check_write(&mut self, _p: &Path) -> Result<(), AnyError> {
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// `UnstableChecker` is a struct so it can be placed inside `GothamState`;
|
||||||
|
/// using type alias for a bool could work, but there's a high chance
|
||||||
|
/// that there might be another type alias pointing to a bool, which
|
||||||
|
/// would override previously used alias.
|
||||||
|
pub struct UnstableChecker {
|
||||||
|
pub unstable: bool,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl UnstableChecker {
|
||||||
|
/// Quits the process if the --unstable flag was not provided.
|
||||||
|
///
|
||||||
|
/// This is intentionally a non-recoverable check so that people cannot probe
|
||||||
|
/// for unstable APIs from stable programs.
|
||||||
|
// NOTE(bartlomieju): keep in sync with `cli/program_state.rs`
|
||||||
|
pub fn check_unstable(&self, api_name: &str) {
|
||||||
|
if !self.unstable {
|
||||||
|
eprintln!(
|
||||||
|
"Unstable API '{}'. The --unstable flag must be provided.",
|
||||||
|
api_name
|
||||||
|
);
|
||||||
|
std::process::exit(70);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/// Helper for checking unstable features. Used for sync ops.
|
||||||
|
pub fn check_unstable(state: &OpState, api_name: &str) {
|
||||||
|
state.borrow::<UnstableChecker>().check_unstable(api_name)
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Helper for checking unstable features. Used for async ops.
|
||||||
|
pub fn check_unstable2(state: &Rc<RefCell<OpState>>, api_name: &str) {
|
||||||
|
let state = state.borrow();
|
||||||
|
state.borrow::<UnstableChecker>().check_unstable(api_name)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn get_declaration() -> PathBuf {
|
||||||
|
PathBuf::from(env!("CARGO_MANIFEST_DIR")).join("lib.deno_net.d.ts")
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn get_unstable_declaration() -> PathBuf {
|
||||||
|
PathBuf::from(env!("CARGO_MANIFEST_DIR")).join("lib.deno_net.unstable.d.ts")
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn init<P: NetPermissions + 'static>(unstable: bool) -> Extension {
|
||||||
|
let mut ops_to_register = vec![];
|
||||||
|
ops_to_register.extend(io::init());
|
||||||
|
ops_to_register.extend(ops::init::<P>());
|
||||||
|
ops_to_register.extend(ops_tls::init::<P>());
|
||||||
|
ops_to_register.extend(ops_http::init());
|
||||||
|
|
||||||
|
Extension::builder()
|
||||||
|
.js(include_js_files!(
|
||||||
|
prefix "deno:extensions/net",
|
||||||
|
"01_net.js",
|
||||||
|
"02_tls.js",
|
||||||
|
"03_http.js",
|
||||||
|
"04_net_unstable.js",
|
||||||
|
))
|
||||||
|
.ops(ops_to_register)
|
||||||
|
.state(move |state| {
|
||||||
|
state.put(UnstableChecker { unstable });
|
||||||
|
Ok(())
|
||||||
|
})
|
||||||
|
.build()
|
||||||
|
}
|
|
@ -1,8 +1,9 @@
|
||||||
// Copyright 2018-2021 the Deno authors. All rights reserved. MIT license.
|
// Copyright 2018-2021 the Deno authors. All rights reserved. MIT license.
|
||||||
use crate::ops::io::TcpStreamResource;
|
|
||||||
use crate::permissions::Permissions;
|
use crate::io::TcpStreamResource;
|
||||||
use crate::resolve_addr::resolve_addr;
|
use crate::resolve_addr::resolve_addr;
|
||||||
use crate::resolve_addr::resolve_addr_sync;
|
use crate::resolve_addr::resolve_addr_sync;
|
||||||
|
use crate::NetPermissions;
|
||||||
use deno_core::error::bad_resource;
|
use deno_core::error::bad_resource;
|
||||||
use deno_core::error::custom_error;
|
use deno_core::error::custom_error;
|
||||||
use deno_core::error::generic_error;
|
use deno_core::error::generic_error;
|
||||||
|
@ -14,7 +15,7 @@ use deno_core::op_sync;
|
||||||
use deno_core::AsyncRefCell;
|
use deno_core::AsyncRefCell;
|
||||||
use deno_core::CancelHandle;
|
use deno_core::CancelHandle;
|
||||||
use deno_core::CancelTryFuture;
|
use deno_core::CancelTryFuture;
|
||||||
use deno_core::Extension;
|
use deno_core::OpPair;
|
||||||
use deno_core::OpState;
|
use deno_core::OpState;
|
||||||
use deno_core::RcRef;
|
use deno_core::RcRef;
|
||||||
use deno_core::Resource;
|
use deno_core::Resource;
|
||||||
|
@ -39,23 +40,21 @@ use trust_dns_resolver::system_conf;
|
||||||
use trust_dns_resolver::AsyncResolver;
|
use trust_dns_resolver::AsyncResolver;
|
||||||
|
|
||||||
#[cfg(unix)]
|
#[cfg(unix)]
|
||||||
use super::net_unix;
|
use super::ops_unix as net_unix;
|
||||||
#[cfg(unix)]
|
#[cfg(unix)]
|
||||||
use crate::ops::io::UnixStreamResource;
|
use crate::io::UnixStreamResource;
|
||||||
#[cfg(unix)]
|
#[cfg(unix)]
|
||||||
use std::path::Path;
|
use std::path::Path;
|
||||||
|
|
||||||
pub fn init() -> Extension {
|
pub fn init<P: NetPermissions + 'static>() -> Vec<OpPair> {
|
||||||
Extension::builder()
|
vec![
|
||||||
.ops(vec![
|
|
||||||
("op_accept", op_async(op_accept)),
|
("op_accept", op_async(op_accept)),
|
||||||
("op_connect", op_async(op_connect)),
|
("op_connect", op_async(op_connect::<P>)),
|
||||||
("op_listen", op_sync(op_listen)),
|
("op_listen", op_sync(op_listen::<P>)),
|
||||||
("op_datagram_receive", op_async(op_datagram_receive)),
|
("op_datagram_receive", op_async(op_datagram_receive)),
|
||||||
("op_datagram_send", op_async(op_datagram_send)),
|
("op_datagram_send", op_async(op_datagram_send::<P>)),
|
||||||
("op_dns_resolve", op_async(op_dns_resolve)),
|
("op_dns_resolve", op_async(op_dns_resolve::<P>)),
|
||||||
])
|
]
|
||||||
.build()
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Serialize)]
|
#[derive(Serialize)]
|
||||||
|
@ -216,11 +215,14 @@ struct SendArgs {
|
||||||
transport_args: ArgsEnum,
|
transport_args: ArgsEnum,
|
||||||
}
|
}
|
||||||
|
|
||||||
async fn op_datagram_send(
|
async fn op_datagram_send<NP>(
|
||||||
state: Rc<RefCell<OpState>>,
|
state: Rc<RefCell<OpState>>,
|
||||||
args: SendArgs,
|
args: SendArgs,
|
||||||
zero_copy: Option<ZeroCopyBuf>,
|
zero_copy: Option<ZeroCopyBuf>,
|
||||||
) -> Result<usize, AnyError> {
|
) -> Result<usize, AnyError>
|
||||||
|
where
|
||||||
|
NP: NetPermissions + 'static,
|
||||||
|
{
|
||||||
let zero_copy = zero_copy.ok_or_else(null_opbuf)?;
|
let zero_copy = zero_copy.ok_or_else(null_opbuf)?;
|
||||||
let zero_copy = zero_copy.clone();
|
let zero_copy = zero_copy.clone();
|
||||||
|
|
||||||
|
@ -232,9 +234,8 @@ async fn op_datagram_send(
|
||||||
} if transport == "udp" => {
|
} if transport == "udp" => {
|
||||||
{
|
{
|
||||||
let mut s = state.borrow_mut();
|
let mut s = state.borrow_mut();
|
||||||
s.borrow_mut::<Permissions>()
|
s.borrow_mut::<NP>()
|
||||||
.net
|
.check_net(&(&args.hostname, Some(args.port)))?;
|
||||||
.check(&(&args.hostname, Some(args.port)))?;
|
|
||||||
}
|
}
|
||||||
let addr = resolve_addr(&args.hostname, args.port)
|
let addr = resolve_addr(&args.hostname, args.port)
|
||||||
.await?
|
.await?
|
||||||
|
@ -259,7 +260,7 @@ async fn op_datagram_send(
|
||||||
let address_path = Path::new(&args.path);
|
let address_path = Path::new(&args.path);
|
||||||
{
|
{
|
||||||
let mut s = state.borrow_mut();
|
let mut s = state.borrow_mut();
|
||||||
s.borrow_mut::<Permissions>().write.check(&address_path)?;
|
s.borrow_mut::<NP>().check_write(&address_path)?;
|
||||||
}
|
}
|
||||||
let resource = state
|
let resource = state
|
||||||
.borrow()
|
.borrow()
|
||||||
|
@ -285,11 +286,14 @@ struct ConnectArgs {
|
||||||
transport_args: ArgsEnum,
|
transport_args: ArgsEnum,
|
||||||
}
|
}
|
||||||
|
|
||||||
async fn op_connect(
|
async fn op_connect<NP>(
|
||||||
state: Rc<RefCell<OpState>>,
|
state: Rc<RefCell<OpState>>,
|
||||||
args: ConnectArgs,
|
args: ConnectArgs,
|
||||||
_: (),
|
_: (),
|
||||||
) -> Result<OpConn, AnyError> {
|
) -> Result<OpConn, AnyError>
|
||||||
|
where
|
||||||
|
NP: NetPermissions + 'static,
|
||||||
|
{
|
||||||
match args {
|
match args {
|
||||||
ConnectArgs {
|
ConnectArgs {
|
||||||
transport,
|
transport,
|
||||||
|
@ -298,9 +302,8 @@ async fn op_connect(
|
||||||
{
|
{
|
||||||
let mut state_ = state.borrow_mut();
|
let mut state_ = state.borrow_mut();
|
||||||
state_
|
state_
|
||||||
.borrow_mut::<Permissions>()
|
.borrow_mut::<NP>()
|
||||||
.net
|
.check_net(&(&args.hostname, Some(args.port)))?;
|
||||||
.check(&(&args.hostname, Some(args.port)))?;
|
|
||||||
}
|
}
|
||||||
let addr = resolve_addr(&args.hostname, args.port)
|
let addr = resolve_addr(&args.hostname, args.port)
|
||||||
.await?
|
.await?
|
||||||
|
@ -335,14 +338,8 @@ async fn op_connect(
|
||||||
super::check_unstable2(&state, "Deno.connect");
|
super::check_unstable2(&state, "Deno.connect");
|
||||||
{
|
{
|
||||||
let mut state_ = state.borrow_mut();
|
let mut state_ = state.borrow_mut();
|
||||||
state_
|
state_.borrow_mut::<NP>().check_read(&address_path)?;
|
||||||
.borrow_mut::<Permissions>()
|
state_.borrow_mut::<NP>().check_write(&address_path)?;
|
||||||
.read
|
|
||||||
.check(&address_path)?;
|
|
||||||
state_
|
|
||||||
.borrow_mut::<Permissions>()
|
|
||||||
.write
|
|
||||||
.check(&address_path)?;
|
|
||||||
}
|
}
|
||||||
let path = args.path;
|
let path = args.path;
|
||||||
let unix_stream = net_unix::UnixStream::connect(Path::new(&path)).await?;
|
let unix_stream = net_unix::UnixStream::connect(Path::new(&path)).await?;
|
||||||
|
@ -451,11 +448,14 @@ fn listen_udp(
|
||||||
Ok((rid, local_addr))
|
Ok((rid, local_addr))
|
||||||
}
|
}
|
||||||
|
|
||||||
fn op_listen(
|
fn op_listen<NP>(
|
||||||
state: &mut OpState,
|
state: &mut OpState,
|
||||||
args: ListenArgs,
|
args: ListenArgs,
|
||||||
_: (),
|
_: (),
|
||||||
) -> Result<OpConn, AnyError> {
|
) -> Result<OpConn, AnyError>
|
||||||
|
where
|
||||||
|
NP: NetPermissions + 'static,
|
||||||
|
{
|
||||||
match args {
|
match args {
|
||||||
ListenArgs {
|
ListenArgs {
|
||||||
transport,
|
transport,
|
||||||
|
@ -466,9 +466,8 @@ fn op_listen(
|
||||||
super::check_unstable(state, "Deno.listenDatagram");
|
super::check_unstable(state, "Deno.listenDatagram");
|
||||||
}
|
}
|
||||||
state
|
state
|
||||||
.borrow_mut::<Permissions>()
|
.borrow_mut::<NP>()
|
||||||
.net
|
.check_net(&(&args.hostname, Some(args.port)))?;
|
||||||
.check(&(&args.hostname, Some(args.port)))?;
|
|
||||||
}
|
}
|
||||||
let addr = resolve_addr_sync(&args.hostname, args.port)?
|
let addr = resolve_addr_sync(&args.hostname, args.port)?
|
||||||
.next()
|
.next()
|
||||||
|
@ -512,9 +511,9 @@ fn op_listen(
|
||||||
if transport == "unixpacket" {
|
if transport == "unixpacket" {
|
||||||
super::check_unstable(state, "Deno.listenDatagram");
|
super::check_unstable(state, "Deno.listenDatagram");
|
||||||
}
|
}
|
||||||
let permissions = state.borrow_mut::<Permissions>();
|
let permissions = state.borrow_mut::<NP>();
|
||||||
permissions.read.check(&address_path)?;
|
permissions.check_read(&address_path)?;
|
||||||
permissions.write.check(&address_path)?;
|
permissions.check_write(&address_path)?;
|
||||||
}
|
}
|
||||||
let (rid, local_addr) = if transport == "unix" {
|
let (rid, local_addr) = if transport == "unix" {
|
||||||
net_unix::listen_unix(state, &address_path)?
|
net_unix::listen_unix(state, &address_path)?
|
||||||
|
@ -592,11 +591,14 @@ pub struct NameServer {
|
||||||
port: u16,
|
port: u16,
|
||||||
}
|
}
|
||||||
|
|
||||||
async fn op_dns_resolve(
|
async fn op_dns_resolve<NP>(
|
||||||
state: Rc<RefCell<OpState>>,
|
state: Rc<RefCell<OpState>>,
|
||||||
args: ResolveAddrArgs,
|
args: ResolveAddrArgs,
|
||||||
_: (),
|
_: (),
|
||||||
) -> Result<Vec<DnsReturnRecord>, AnyError> {
|
) -> Result<Vec<DnsReturnRecord>, AnyError>
|
||||||
|
where
|
||||||
|
NP: NetPermissions + 'static,
|
||||||
|
{
|
||||||
let ResolveAddrArgs {
|
let ResolveAddrArgs {
|
||||||
query,
|
query,
|
||||||
record_type,
|
record_type,
|
||||||
|
@ -621,14 +623,14 @@ async fn op_dns_resolve(
|
||||||
|
|
||||||
{
|
{
|
||||||
let mut s = state.borrow_mut();
|
let mut s = state.borrow_mut();
|
||||||
let perm = s.borrow_mut::<Permissions>();
|
let perm = s.borrow_mut::<NP>();
|
||||||
|
|
||||||
// Checks permission against the name servers which will be actually queried.
|
// Checks permission against the name servers which will be actually queried.
|
||||||
for ns in config.name_servers() {
|
for ns in config.name_servers() {
|
||||||
let socker_addr = &ns.socket_addr;
|
let socker_addr = &ns.socket_addr;
|
||||||
let ip = socker_addr.ip().to_string();
|
let ip = socker_addr.ip().to_string();
|
||||||
let port = socker_addr.port();
|
let port = socker_addr.port();
|
||||||
perm.net.check(&(ip, Some(port)))?;
|
perm.check_net(&(ip, Some(port)))?;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,8 +1,8 @@
|
||||||
// Copyright 2018-2021 the Deno authors. All rights reserved. MIT license.
|
// Copyright 2018-2021 the Deno authors. All rights reserved. MIT license.
|
||||||
|
|
||||||
use crate::ops::io::TcpStreamResource;
|
use crate::io::TcpStreamResource;
|
||||||
use crate::ops::io::TlsStreamResource;
|
use crate::io::TlsStreamResource;
|
||||||
use crate::ops::tls::TlsStream;
|
use crate::ops_tls::TlsStream;
|
||||||
use deno_core::error::bad_resource_id;
|
use deno_core::error::bad_resource_id;
|
||||||
use deno_core::error::null_opbuf;
|
use deno_core::error::null_opbuf;
|
||||||
use deno_core::error::type_error;
|
use deno_core::error::type_error;
|
||||||
|
@ -17,7 +17,7 @@ use deno_core::AsyncRefCell;
|
||||||
use deno_core::ByteString;
|
use deno_core::ByteString;
|
||||||
use deno_core::CancelHandle;
|
use deno_core::CancelHandle;
|
||||||
use deno_core::CancelTryFuture;
|
use deno_core::CancelTryFuture;
|
||||||
use deno_core::Extension;
|
use deno_core::OpPair;
|
||||||
use deno_core::OpState;
|
use deno_core::OpState;
|
||||||
use deno_core::RcRef;
|
use deno_core::RcRef;
|
||||||
use deno_core::Resource;
|
use deno_core::Resource;
|
||||||
|
@ -46,17 +46,15 @@ use tokio::net::TcpStream;
|
||||||
use tokio::sync::oneshot;
|
use tokio::sync::oneshot;
|
||||||
use tokio_util::io::StreamReader;
|
use tokio_util::io::StreamReader;
|
||||||
|
|
||||||
pub fn init() -> Extension {
|
pub fn init() -> Vec<OpPair> {
|
||||||
Extension::builder()
|
vec![
|
||||||
.ops(vec![
|
|
||||||
("op_http_start", op_sync(op_http_start)),
|
("op_http_start", op_sync(op_http_start)),
|
||||||
("op_http_request_next", op_async(op_http_request_next)),
|
("op_http_request_next", op_async(op_http_request_next)),
|
||||||
("op_http_request_read", op_async(op_http_request_read)),
|
("op_http_request_read", op_async(op_http_request_read)),
|
||||||
("op_http_response", op_async(op_http_response)),
|
("op_http_response", op_async(op_http_response)),
|
||||||
("op_http_response_write", op_async(op_http_response_write)),
|
("op_http_response_write", op_async(op_http_response_write)),
|
||||||
("op_http_response_close", op_async(op_http_response_close)),
|
("op_http_response_close", op_async(op_http_response_close)),
|
||||||
])
|
]
|
||||||
.build()
|
|
||||||
}
|
}
|
||||||
|
|
||||||
struct ServiceInner {
|
struct ServiceInner {
|
|
@ -3,14 +3,14 @@
|
||||||
pub use rustls;
|
pub use rustls;
|
||||||
pub use webpki;
|
pub use webpki;
|
||||||
|
|
||||||
use crate::ops::io::TcpStreamResource;
|
use crate::io::TcpStreamResource;
|
||||||
use crate::ops::io::TlsStreamResource;
|
use crate::io::TlsStreamResource;
|
||||||
use crate::ops::net::IpAddr;
|
use crate::ops::IpAddr;
|
||||||
use crate::ops::net::OpAddr;
|
use crate::ops::OpAddr;
|
||||||
use crate::ops::net::OpConn;
|
use crate::ops::OpConn;
|
||||||
use crate::permissions::Permissions;
|
|
||||||
use crate::resolve_addr::resolve_addr;
|
use crate::resolve_addr::resolve_addr;
|
||||||
use crate::resolve_addr::resolve_addr_sync;
|
use crate::resolve_addr::resolve_addr_sync;
|
||||||
|
use crate::NetPermissions;
|
||||||
use deno_core::error::bad_resource;
|
use deno_core::error::bad_resource;
|
||||||
use deno_core::error::bad_resource_id;
|
use deno_core::error::bad_resource_id;
|
||||||
use deno_core::error::custom_error;
|
use deno_core::error::custom_error;
|
||||||
|
@ -31,7 +31,7 @@ use deno_core::op_sync;
|
||||||
use deno_core::AsyncRefCell;
|
use deno_core::AsyncRefCell;
|
||||||
use deno_core::CancelHandle;
|
use deno_core::CancelHandle;
|
||||||
use deno_core::CancelTryFuture;
|
use deno_core::CancelTryFuture;
|
||||||
use deno_core::Extension;
|
use deno_core::OpPair;
|
||||||
use deno_core::OpState;
|
use deno_core::OpState;
|
||||||
use deno_core::RcRef;
|
use deno_core::RcRef;
|
||||||
use deno_core::Resource;
|
use deno_core::Resource;
|
||||||
|
@ -662,15 +662,13 @@ impl Write for ImplementWriteTrait<'_, TcpStream> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn init() -> Extension {
|
pub fn init<P: NetPermissions + 'static>() -> Vec<OpPair> {
|
||||||
Extension::builder()
|
vec![
|
||||||
.ops(vec![
|
("op_start_tls", op_async(op_start_tls::<P>)),
|
||||||
("op_start_tls", op_async(op_start_tls)),
|
("op_connect_tls", op_async(op_connect_tls::<P>)),
|
||||||
("op_connect_tls", op_async(op_connect_tls)),
|
("op_listen_tls", op_sync(op_listen_tls::<P>)),
|
||||||
("op_listen_tls", op_sync(op_listen_tls)),
|
|
||||||
("op_accept_tls", op_async(op_accept_tls)),
|
("op_accept_tls", op_async(op_accept_tls)),
|
||||||
])
|
]
|
||||||
.build()
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Deserialize)]
|
#[derive(Deserialize)]
|
||||||
|
@ -690,11 +688,14 @@ struct StartTlsArgs {
|
||||||
hostname: String,
|
hostname: String,
|
||||||
}
|
}
|
||||||
|
|
||||||
async fn op_start_tls(
|
async fn op_start_tls<NP>(
|
||||||
state: Rc<RefCell<OpState>>,
|
state: Rc<RefCell<OpState>>,
|
||||||
args: StartTlsArgs,
|
args: StartTlsArgs,
|
||||||
_: (),
|
_: (),
|
||||||
) -> Result<OpConn, AnyError> {
|
) -> Result<OpConn, AnyError>
|
||||||
|
where
|
||||||
|
NP: NetPermissions + 'static,
|
||||||
|
{
|
||||||
let rid = args.rid;
|
let rid = args.rid;
|
||||||
let hostname = match &*args.hostname {
|
let hostname = match &*args.hostname {
|
||||||
"" => "localhost",
|
"" => "localhost",
|
||||||
|
@ -705,10 +706,10 @@ async fn op_start_tls(
|
||||||
{
|
{
|
||||||
super::check_unstable2(&state, "Deno.startTls");
|
super::check_unstable2(&state, "Deno.startTls");
|
||||||
let mut s = state.borrow_mut();
|
let mut s = state.borrow_mut();
|
||||||
let permissions = s.borrow_mut::<Permissions>();
|
let permissions = s.borrow_mut::<NP>();
|
||||||
permissions.net.check(&(hostname, Some(0)))?;
|
permissions.check_net(&(hostname, Some(0)))?;
|
||||||
if let Some(path) = cert_file {
|
if let Some(path) = cert_file {
|
||||||
permissions.read.check(Path::new(path))?;
|
permissions.check_read(Path::new(path))?;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -763,11 +764,14 @@ async fn op_start_tls(
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
async fn op_connect_tls(
|
async fn op_connect_tls<NP>(
|
||||||
state: Rc<RefCell<OpState>>,
|
state: Rc<RefCell<OpState>>,
|
||||||
args: ConnectTlsArgs,
|
args: ConnectTlsArgs,
|
||||||
_: (),
|
_: (),
|
||||||
) -> Result<OpConn, AnyError> {
|
) -> Result<OpConn, AnyError>
|
||||||
|
where
|
||||||
|
NP: NetPermissions + 'static,
|
||||||
|
{
|
||||||
assert_eq!(args.transport, "tcp");
|
assert_eq!(args.transport, "tcp");
|
||||||
let hostname = match &*args.hostname {
|
let hostname = match &*args.hostname {
|
||||||
"" => "localhost",
|
"" => "localhost",
|
||||||
|
@ -778,10 +782,10 @@ async fn op_connect_tls(
|
||||||
|
|
||||||
{
|
{
|
||||||
let mut s = state.borrow_mut();
|
let mut s = state.borrow_mut();
|
||||||
let permissions = s.borrow_mut::<Permissions>();
|
let permissions = s.borrow_mut::<NP>();
|
||||||
permissions.net.check(&(hostname, Some(port)))?;
|
permissions.check_net(&(hostname, Some(port)))?;
|
||||||
if let Some(path) = cert_file {
|
if let Some(path) = cert_file {
|
||||||
permissions.read.check(Path::new(path))?;
|
permissions.check_read(Path::new(path))?;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -912,11 +916,14 @@ pub struct ListenTlsArgs {
|
||||||
alpn_protocols: Option<Vec<String>>,
|
alpn_protocols: Option<Vec<String>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
fn op_listen_tls(
|
fn op_listen_tls<NP>(
|
||||||
state: &mut OpState,
|
state: &mut OpState,
|
||||||
args: ListenTlsArgs,
|
args: ListenTlsArgs,
|
||||||
_: (),
|
_: (),
|
||||||
) -> Result<OpConn, AnyError> {
|
) -> Result<OpConn, AnyError>
|
||||||
|
where
|
||||||
|
NP: NetPermissions + 'static,
|
||||||
|
{
|
||||||
assert_eq!(args.transport, "tcp");
|
assert_eq!(args.transport, "tcp");
|
||||||
let hostname = &*args.hostname;
|
let hostname = &*args.hostname;
|
||||||
let port = args.port;
|
let port = args.port;
|
||||||
|
@ -924,10 +931,10 @@ fn op_listen_tls(
|
||||||
let key_file = &*args.key_file;
|
let key_file = &*args.key_file;
|
||||||
|
|
||||||
{
|
{
|
||||||
let permissions = state.borrow_mut::<Permissions>();
|
let permissions = state.borrow_mut::<NP>();
|
||||||
permissions.net.check(&(hostname, Some(port)))?;
|
permissions.check_net(&(hostname, Some(port)))?;
|
||||||
permissions.read.check(Path::new(cert_file))?;
|
permissions.check_read(Path::new(cert_file))?;
|
||||||
permissions.read.check(Path::new(key_file))?;
|
permissions.check_read(Path::new(key_file))?;
|
||||||
}
|
}
|
||||||
|
|
||||||
let mut tls_config = ServerConfig::new(NoClientAuth::new());
|
let mut tls_config = ServerConfig::new(NoClientAuth::new());
|
|
@ -1,12 +1,11 @@
|
||||||
// Copyright 2018-2021 the Deno authors. All rights reserved. MIT license.
|
// Copyright 2018-2021 the Deno authors. All rights reserved. MIT license.
|
||||||
|
|
||||||
use super::utils::into_string;
|
use crate::io::UnixStreamResource;
|
||||||
use crate::ops::io::UnixStreamResource;
|
use crate::ops::AcceptArgs;
|
||||||
use crate::ops::net::AcceptArgs;
|
use crate::ops::OpAddr;
|
||||||
use crate::ops::net::OpAddr;
|
use crate::ops::OpConn;
|
||||||
use crate::ops::net::OpConn;
|
use crate::ops::OpPacket;
|
||||||
use crate::ops::net::OpPacket;
|
use crate::ops::ReceiveArgs;
|
||||||
use crate::ops::net::ReceiveArgs;
|
|
||||||
use deno_core::error::bad_resource;
|
use deno_core::error::bad_resource;
|
||||||
use deno_core::error::custom_error;
|
use deno_core::error::custom_error;
|
||||||
use deno_core::error::null_opbuf;
|
use deno_core::error::null_opbuf;
|
||||||
|
@ -29,6 +28,14 @@ use tokio::net::UnixDatagram;
|
||||||
use tokio::net::UnixListener;
|
use tokio::net::UnixListener;
|
||||||
pub use tokio::net::UnixStream;
|
pub use tokio::net::UnixStream;
|
||||||
|
|
||||||
|
/// A utility function to map OsStrings to Strings
|
||||||
|
pub fn into_string(s: std::ffi::OsString) -> Result<String, AnyError> {
|
||||||
|
s.into_string().map_err(|s| {
|
||||||
|
let message = format!("File name or path {:?} is not valid UTF-8", s);
|
||||||
|
custom_error("InvalidData", message)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
struct UnixListenerResource {
|
struct UnixListenerResource {
|
||||||
listener: AsyncRefCell<UnixListener>,
|
listener: AsyncRefCell<UnixListener>,
|
||||||
cancel: CancelHandle,
|
cancel: CancelHandle,
|
|
@ -23,6 +23,7 @@ deno_console = { version = "0.10.0", path = "../extensions/console" }
|
||||||
deno_core = { version = "0.92.0", path = "../core" }
|
deno_core = { version = "0.92.0", path = "../core" }
|
||||||
deno_crypto = { version = "0.24.0", path = "../extensions/crypto" }
|
deno_crypto = { version = "0.24.0", path = "../extensions/crypto" }
|
||||||
deno_fetch = { version = "0.32.0", path = "../extensions/fetch" }
|
deno_fetch = { version = "0.32.0", path = "../extensions/fetch" }
|
||||||
|
deno_net = { version = "0.1.0", path = "../extensions/net" }
|
||||||
deno_timers = { version = "0.8.0", path = "../extensions/timers" }
|
deno_timers = { version = "0.8.0", path = "../extensions/timers" }
|
||||||
deno_url = { version = "0.10.0", path = "../extensions/url" }
|
deno_url = { version = "0.10.0", path = "../extensions/url" }
|
||||||
deno_web = { version = "0.41.0", path = "../extensions/web" }
|
deno_web = { version = "0.41.0", path = "../extensions/web" }
|
||||||
|
@ -41,6 +42,7 @@ deno_console = { version = "0.10.0", path = "../extensions/console" }
|
||||||
deno_core = { version = "0.92.0", path = "../core" }
|
deno_core = { version = "0.92.0", path = "../core" }
|
||||||
deno_crypto = { version = "0.24.0", path = "../extensions/crypto" }
|
deno_crypto = { version = "0.24.0", path = "../extensions/crypto" }
|
||||||
deno_fetch = { version = "0.32.0", path = "../extensions/fetch" }
|
deno_fetch = { version = "0.32.0", path = "../extensions/fetch" }
|
||||||
|
deno_net = { version = "0.1.0", path = "../extensions/net" }
|
||||||
deno_timers = { version = "0.8.0", path = "../extensions/timers" }
|
deno_timers = { version = "0.8.0", path = "../extensions/timers" }
|
||||||
deno_url = { version = "0.10.0", path = "../extensions/url" }
|
deno_url = { version = "0.10.0", path = "../extensions/url" }
|
||||||
deno_web = { version = "0.41.0", path = "../extensions/web" }
|
deno_web = { version = "0.41.0", path = "../extensions/web" }
|
||||||
|
@ -50,7 +52,6 @@ deno_websocket = { version = "0.15.0", path = "../extensions/websocket" }
|
||||||
deno_webstorage = { version = "0.5.0", path = "../extensions/webstorage" }
|
deno_webstorage = { version = "0.5.0", path = "../extensions/webstorage" }
|
||||||
|
|
||||||
atty = "0.2.14"
|
atty = "0.2.14"
|
||||||
bytes = "1"
|
|
||||||
dlopen = "0.1.8"
|
dlopen = "0.1.8"
|
||||||
encoding_rs = "0.8.28"
|
encoding_rs = "0.8.28"
|
||||||
filetime = "0.2.14"
|
filetime = "0.2.14"
|
||||||
|
@ -64,17 +65,11 @@ notify = "5.0.0-pre.7"
|
||||||
percent-encoding = "2.1.0"
|
percent-encoding = "2.1.0"
|
||||||
regex = "1.4.3"
|
regex = "1.4.3"
|
||||||
ring = "0.16.20"
|
ring = "0.16.20"
|
||||||
rustls = "0.19.0"
|
|
||||||
serde = { version = "1.0.125", features = ["derive"] }
|
serde = { version = "1.0.125", features = ["derive"] }
|
||||||
sys-info = "0.9.0"
|
sys-info = "0.9.0"
|
||||||
termcolor = "1.1.2"
|
termcolor = "1.1.2"
|
||||||
tokio = { version = "1.7.1", features = ["full"] }
|
tokio = { version = "1.7.1", features = ["full"] }
|
||||||
tokio-util = { version = "0.6", features = ["io"] }
|
|
||||||
uuid = { version = "0.8.2", features = ["v4"] }
|
uuid = { version = "0.8.2", features = ["v4"] }
|
||||||
webpki = "0.21.4"
|
|
||||||
webpki-roots = "0.21.1"
|
|
||||||
trust-dns-proto = "0.20.3"
|
|
||||||
trust-dns-resolver = { version = "0.20.3", features = ["tokio-runtime", "serde-config"] }
|
|
||||||
|
|
||||||
[target.'cfg(windows)'.dependencies]
|
[target.'cfg(windows)'.dependencies]
|
||||||
fwdansi = "1.1.0"
|
fwdansi = "1.1.0"
|
||||||
|
|
|
@ -59,6 +59,7 @@ fn create_runtime_snapshot(snapshot_path: &Path, files: Vec<PathBuf>) {
|
||||||
deno_broadcast_channel::InMemoryBroadcastChannel::default(),
|
deno_broadcast_channel::InMemoryBroadcastChannel::default(),
|
||||||
false, // No --unstable.
|
false, // No --unstable.
|
||||||
),
|
),
|
||||||
|
deno_net::init::<deno_net::NoNetPermissions>(false), // No --unstable.
|
||||||
];
|
];
|
||||||
|
|
||||||
let js_runtime = JsRuntime::new(RuntimeOptions {
|
let js_runtime = JsRuntime::new(RuntimeOptions {
|
||||||
|
|
|
@ -2,6 +2,9 @@
|
||||||
"use strict";
|
"use strict";
|
||||||
|
|
||||||
((window) => {
|
((window) => {
|
||||||
|
const core = window.Deno.core;
|
||||||
|
const { BadResource, Interrupted } = core;
|
||||||
|
|
||||||
class NotFound extends Error {
|
class NotFound extends Error {
|
||||||
constructor(msg) {
|
constructor(msg) {
|
||||||
super(msg);
|
super(msg);
|
||||||
|
@ -86,13 +89,6 @@
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
class Interrupted extends Error {
|
|
||||||
constructor(msg) {
|
|
||||||
super(msg);
|
|
||||||
this.name = "Interrupted";
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
class WriteZero extends Error {
|
class WriteZero extends Error {
|
||||||
constructor(msg) {
|
constructor(msg) {
|
||||||
super(msg);
|
super(msg);
|
||||||
|
@ -107,13 +103,6 @@
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
class BadResource extends Error {
|
|
||||||
constructor(msg) {
|
|
||||||
super(msg);
|
|
||||||
this.name = "BadResource";
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
class Http extends Error {
|
class Http extends Error {
|
||||||
constructor(msg) {
|
constructor(msg) {
|
||||||
super(msg);
|
super(msg);
|
||||||
|
|
|
@ -4,6 +4,7 @@ pub use deno_broadcast_channel;
|
||||||
pub use deno_console;
|
pub use deno_console;
|
||||||
pub use deno_crypto;
|
pub use deno_crypto;
|
||||||
pub use deno_fetch;
|
pub use deno_fetch;
|
||||||
|
pub use deno_net;
|
||||||
pub use deno_timers;
|
pub use deno_timers;
|
||||||
pub use deno_url;
|
pub use deno_url;
|
||||||
pub use deno_web;
|
pub use deno_web;
|
||||||
|
@ -20,7 +21,6 @@ pub mod js;
|
||||||
pub mod metrics;
|
pub mod metrics;
|
||||||
pub mod ops;
|
pub mod ops;
|
||||||
pub mod permissions;
|
pub mod permissions;
|
||||||
pub mod resolve_addr;
|
|
||||||
pub mod tokio_util;
|
pub mod tokio_util;
|
||||||
pub mod web_worker;
|
pub mod web_worker;
|
||||||
pub mod worker;
|
pub mod worker;
|
||||||
|
|
|
@ -1,6 +1,5 @@
|
||||||
// Copyright 2018-2021 the Deno authors. All rights reserved. MIT license.
|
// Copyright 2018-2021 the Deno authors. All rights reserved. MIT license.
|
||||||
|
|
||||||
use crate::ops::tls;
|
|
||||||
use deno_core::error::null_opbuf;
|
use deno_core::error::null_opbuf;
|
||||||
use deno_core::error::resource_unavailable;
|
use deno_core::error::resource_unavailable;
|
||||||
use deno_core::error::AnyError;
|
use deno_core::error::AnyError;
|
||||||
|
@ -17,6 +16,9 @@ use deno_core::RcRef;
|
||||||
use deno_core::Resource;
|
use deno_core::Resource;
|
||||||
use deno_core::ResourceId;
|
use deno_core::ResourceId;
|
||||||
use deno_core::ZeroCopyBuf;
|
use deno_core::ZeroCopyBuf;
|
||||||
|
use deno_net::io::TcpStreamResource;
|
||||||
|
use deno_net::io::TlsStreamResource;
|
||||||
|
use deno_net::io::UnixStreamResource;
|
||||||
use std::borrow::Cow;
|
use std::borrow::Cow;
|
||||||
use std::cell::RefCell;
|
use std::cell::RefCell;
|
||||||
use std::io::Read;
|
use std::io::Read;
|
||||||
|
@ -26,13 +28,10 @@ use tokio::io::AsyncRead;
|
||||||
use tokio::io::AsyncReadExt;
|
use tokio::io::AsyncReadExt;
|
||||||
use tokio::io::AsyncWrite;
|
use tokio::io::AsyncWrite;
|
||||||
use tokio::io::AsyncWriteExt;
|
use tokio::io::AsyncWriteExt;
|
||||||
use tokio::net::tcp;
|
|
||||||
use tokio::process;
|
use tokio::process;
|
||||||
|
|
||||||
#[cfg(unix)]
|
#[cfg(unix)]
|
||||||
use std::os::unix::io::FromRawFd;
|
use std::os::unix::io::FromRawFd;
|
||||||
#[cfg(unix)]
|
|
||||||
use tokio::net::unix;
|
|
||||||
|
|
||||||
#[cfg(windows)]
|
#[cfg(windows)]
|
||||||
use std::os::windows::io::FromRawHandle;
|
use std::os::windows::io::FromRawHandle;
|
||||||
|
@ -238,70 +237,6 @@ where
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// A full duplex resource has a read and write ends that are completely
|
|
||||||
/// independent, like TCP/Unix sockets and TLS streams.
|
|
||||||
#[derive(Debug)]
|
|
||||||
pub struct FullDuplexResource<R, W> {
|
|
||||||
rd: AsyncRefCell<R>,
|
|
||||||
wr: AsyncRefCell<W>,
|
|
||||||
// When a full-duplex resource is closed, all pending 'read' ops are
|
|
||||||
// canceled, while 'write' ops are allowed to complete. Therefore only
|
|
||||||
// 'read' futures should be attached to this cancel handle.
|
|
||||||
cancel_handle: CancelHandle,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<R, W> FullDuplexResource<R, W>
|
|
||||||
where
|
|
||||||
R: AsyncRead + Unpin + 'static,
|
|
||||||
W: AsyncWrite + Unpin + 'static,
|
|
||||||
{
|
|
||||||
pub fn new((rd, wr): (R, W)) -> Self {
|
|
||||||
Self {
|
|
||||||
rd: rd.into(),
|
|
||||||
wr: wr.into(),
|
|
||||||
cancel_handle: Default::default(),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn into_inner(self) -> (R, W) {
|
|
||||||
(self.rd.into_inner(), self.wr.into_inner())
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn rd_borrow_mut(self: &Rc<Self>) -> AsyncMutFuture<R> {
|
|
||||||
RcRef::map(self, |r| &r.rd).borrow_mut()
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn wr_borrow_mut(self: &Rc<Self>) -> AsyncMutFuture<W> {
|
|
||||||
RcRef::map(self, |r| &r.wr).borrow_mut()
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn cancel_handle(self: &Rc<Self>) -> RcRef<CancelHandle> {
|
|
||||||
RcRef::map(self, |r| &r.cancel_handle)
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn cancel_read_ops(&self) {
|
|
||||||
self.cancel_handle.cancel()
|
|
||||||
}
|
|
||||||
|
|
||||||
async fn read(self: &Rc<Self>, buf: &mut [u8]) -> Result<usize, AnyError> {
|
|
||||||
let mut rd = self.rd_borrow_mut().await;
|
|
||||||
let nread = rd.read(buf).try_or_cancel(self.cancel_handle()).await?;
|
|
||||||
Ok(nread)
|
|
||||||
}
|
|
||||||
|
|
||||||
async fn write(self: &Rc<Self>, buf: &[u8]) -> Result<usize, AnyError> {
|
|
||||||
let mut wr = self.wr_borrow_mut().await;
|
|
||||||
let nwritten = wr.write(buf).await?;
|
|
||||||
Ok(nwritten)
|
|
||||||
}
|
|
||||||
|
|
||||||
async fn shutdown(self: &Rc<Self>) -> Result<(), AnyError> {
|
|
||||||
let mut wr = self.wr_borrow_mut().await;
|
|
||||||
wr.shutdown().await?;
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub type ChildStdinResource = WriteOnlyResource<process::ChildStdin>;
|
pub type ChildStdinResource = WriteOnlyResource<process::ChildStdin>;
|
||||||
|
|
||||||
impl Resource for ChildStdinResource {
|
impl Resource for ChildStdinResource {
|
||||||
|
@ -334,64 +269,6 @@ impl Resource for ChildStderrResource {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub type TcpStreamResource =
|
|
||||||
FullDuplexResource<tcp::OwnedReadHalf, tcp::OwnedWriteHalf>;
|
|
||||||
|
|
||||||
impl Resource for TcpStreamResource {
|
|
||||||
fn name(&self) -> Cow<str> {
|
|
||||||
"tcpStream".into()
|
|
||||||
}
|
|
||||||
|
|
||||||
fn close(self: Rc<Self>) {
|
|
||||||
self.cancel_read_ops();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub type TlsStreamResource = FullDuplexResource<tls::ReadHalf, tls::WriteHalf>;
|
|
||||||
|
|
||||||
impl Resource for TlsStreamResource {
|
|
||||||
fn name(&self) -> Cow<str> {
|
|
||||||
"tlsStream".into()
|
|
||||||
}
|
|
||||||
|
|
||||||
fn close(self: Rc<Self>) {
|
|
||||||
self.cancel_read_ops();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[cfg(unix)]
|
|
||||||
pub type UnixStreamResource =
|
|
||||||
FullDuplexResource<unix::OwnedReadHalf, unix::OwnedWriteHalf>;
|
|
||||||
|
|
||||||
#[cfg(not(unix))]
|
|
||||||
struct UnixStreamResource;
|
|
||||||
|
|
||||||
#[cfg(not(unix))]
|
|
||||||
impl UnixStreamResource {
|
|
||||||
async fn read(self: &Rc<Self>, _buf: &mut [u8]) -> Result<usize, AnyError> {
|
|
||||||
unreachable!()
|
|
||||||
}
|
|
||||||
async fn write(self: &Rc<Self>, _buf: &[u8]) -> Result<usize, AnyError> {
|
|
||||||
unreachable!()
|
|
||||||
}
|
|
||||||
async fn shutdown(self: &Rc<Self>) -> Result<(), AnyError> {
|
|
||||||
unreachable!()
|
|
||||||
}
|
|
||||||
fn cancel_read_ops(&self) {
|
|
||||||
unreachable!()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Resource for UnixStreamResource {
|
|
||||||
fn name(&self) -> Cow<str> {
|
|
||||||
"unixStream".into()
|
|
||||||
}
|
|
||||||
|
|
||||||
fn close(self: Rc<Self>) {
|
|
||||||
self.cancel_read_ops();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Debug, Default)]
|
#[derive(Debug, Default)]
|
||||||
pub struct StdFileResource {
|
pub struct StdFileResource {
|
||||||
pub fs_file:
|
pub fs_file:
|
||||||
|
|
|
@ -2,18 +2,13 @@
|
||||||
|
|
||||||
pub mod fs;
|
pub mod fs;
|
||||||
pub mod fs_events;
|
pub mod fs_events;
|
||||||
pub mod http;
|
|
||||||
pub mod io;
|
pub mod io;
|
||||||
pub mod net;
|
|
||||||
#[cfg(unix)]
|
|
||||||
mod net_unix;
|
|
||||||
pub mod os;
|
pub mod os;
|
||||||
pub mod permissions;
|
pub mod permissions;
|
||||||
pub mod plugin;
|
pub mod plugin;
|
||||||
pub mod process;
|
pub mod process;
|
||||||
pub mod runtime;
|
pub mod runtime;
|
||||||
pub mod signal;
|
pub mod signal;
|
||||||
pub mod tls;
|
|
||||||
pub mod tty;
|
pub mod tty;
|
||||||
mod utils;
|
mod utils;
|
||||||
pub mod web_worker;
|
pub mod web_worker;
|
||||||
|
|
|
@ -962,6 +962,23 @@ impl Permissions {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl deno_net::NetPermissions for Permissions {
|
||||||
|
fn check_net<T: AsRef<str>>(
|
||||||
|
&mut self,
|
||||||
|
host: &(T, Option<u16>),
|
||||||
|
) -> Result<(), AnyError> {
|
||||||
|
self.net.check(host)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn check_read(&mut self, path: &Path) -> Result<(), AnyError> {
|
||||||
|
self.read.check(path)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn check_write(&mut self, path: &Path) -> Result<(), AnyError> {
|
||||||
|
self.write.check(path)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl deno_fetch::FetchPermissions for Permissions {
|
impl deno_fetch::FetchPermissions for Permissions {
|
||||||
fn check_net_url(&mut self, url: &url::Url) -> Result<(), AnyError> {
|
fn check_net_url(&mut self, url: &url::Url) -> Result<(), AnyError> {
|
||||||
self.net.check_url(url)
|
self.net.check_url(url)
|
||||||
|
|
|
@ -330,14 +330,12 @@ impl WebWorker {
|
||||||
vec![
|
vec![
|
||||||
ops::fs_events::init(),
|
ops::fs_events::init(),
|
||||||
ops::fs::init(),
|
ops::fs::init(),
|
||||||
ops::net::init(),
|
deno_net::init::<Permissions>(options.unstable),
|
||||||
ops::os::init(),
|
ops::os::init(),
|
||||||
ops::http::init(),
|
|
||||||
ops::permissions::init(),
|
ops::permissions::init(),
|
||||||
ops::plugin::init(),
|
ops::plugin::init(),
|
||||||
ops::process::init(),
|
ops::process::init(),
|
||||||
ops::signal::init(),
|
ops::signal::init(),
|
||||||
ops::tls::init(),
|
|
||||||
ops::tty::init(),
|
ops::tty::init(),
|
||||||
ops::io::init_stdio(),
|
ops::io::init_stdio(),
|
||||||
]
|
]
|
||||||
|
|
|
@ -120,16 +120,14 @@ impl MainWorker {
|
||||||
ops::worker_host::init(options.create_web_worker_cb.clone()),
|
ops::worker_host::init(options.create_web_worker_cb.clone()),
|
||||||
ops::fs_events::init(),
|
ops::fs_events::init(),
|
||||||
ops::fs::init(),
|
ops::fs::init(),
|
||||||
ops::http::init(),
|
|
||||||
ops::io::init(),
|
ops::io::init(),
|
||||||
ops::io::init_stdio(),
|
ops::io::init_stdio(),
|
||||||
ops::net::init(),
|
deno_net::init::<Permissions>(options.unstable),
|
||||||
ops::os::init(),
|
ops::os::init(),
|
||||||
ops::permissions::init(),
|
ops::permissions::init(),
|
||||||
ops::plugin::init(),
|
ops::plugin::init(),
|
||||||
ops::process::init(),
|
ops::process::init(),
|
||||||
ops::signal::init(),
|
ops::signal::init(),
|
||||||
ops::tls::init(),
|
|
||||||
ops::tty::init(),
|
ops::tty::init(),
|
||||||
// Permissions ext (worker specific state)
|
// Permissions ext (worker specific state)
|
||||||
perm_ext,
|
perm_ext,
|
||||||
|
|
Loading…
Reference in a new issue