mirror of
https://github.com/denoland/deno.git
synced 2024-11-21 15:04:11 -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_fetch",
|
||||
"deno_lint",
|
||||
"deno_net",
|
||||
"deno_runtime",
|
||||
"deno_timers",
|
||||
"deno_url",
|
||||
|
@ -702,17 +703,37 @@ dependencies = [
|
|||
"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]]
|
||||
name = "deno_runtime"
|
||||
version = "0.18.0"
|
||||
dependencies = [
|
||||
"atty",
|
||||
"bytes",
|
||||
"deno_broadcast_channel",
|
||||
"deno_console",
|
||||
"deno_core",
|
||||
"deno_crypto",
|
||||
"deno_fetch",
|
||||
"deno_net",
|
||||
"deno_timers",
|
||||
"deno_url",
|
||||
"deno_web",
|
||||
|
@ -735,18 +756,12 @@ dependencies = [
|
|||
"percent-encoding",
|
||||
"regex",
|
||||
"ring",
|
||||
"rustls",
|
||||
"serde",
|
||||
"sys-info",
|
||||
"termcolor",
|
||||
"test_util",
|
||||
"tokio",
|
||||
"tokio-util",
|
||||
"trust-dns-proto",
|
||||
"trust-dns-resolver",
|
||||
"uuid",
|
||||
"webpki",
|
||||
"webpki-roots",
|
||||
"winapi 0.3.9",
|
||||
"winres",
|
||||
]
|
||||
|
|
|
@ -12,6 +12,7 @@ members = [
|
|||
"extensions/console",
|
||||
"extensions/crypto",
|
||||
"extensions/fetch",
|
||||
"extensions/net",
|
||||
"extensions/timers",
|
||||
"extensions/url",
|
||||
"extensions/web",
|
||||
|
|
|
@ -25,6 +25,7 @@ deno_console = { version = "0.10.0", path = "../extensions/console" }
|
|||
deno_core = { version = "0.92.0", path = "../core" }
|
||||
deno_crypto = { version = "0.24.0", path = "../extensions/crypto" }
|
||||
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_url = { version = "0.10.0", path = "../extensions/url" }
|
||||
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::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.
|
||||
for (_, path) in op_crate_libs.iter() {
|
||||
|
@ -302,6 +305,14 @@ fn main() {
|
|||
"cargo:rustc-env=DENO_BROADCAST_CHANNEL_LIB_PATH={}",
|
||||
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=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 lib="esnext" />
|
||||
/// <reference lib="deno.net" />
|
||||
|
||||
/** Deno provides extra properties on `import.meta`. These are included here
|
||||
* to ensure that these are still available when using the Deno namespace in
|
||||
|
@ -1784,149 +1785,6 @@ declare namespace Deno {
|
|||
* Requires `allow-write` permission. */
|
||||
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 {
|
||||
opsDispatched: 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 lib="deno.ns" />
|
||||
/// <reference lib="deno.net_unstable" />
|
||||
|
||||
declare namespace Deno {
|
||||
/**
|
||||
|
@ -812,232 +813,6 @@ declare namespace Deno {
|
|||
mtime: number | Date,
|
||||
): 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
|
||||
* enum.
|
||||
*
|
||||
|
@ -1182,36 +957,6 @@ declare namespace Deno {
|
|||
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. */
|
||||
export interface TestDefinition {
|
||||
/** 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_CRYPTO_LIB,
|
||||
crate::tsc::DENO_BROADCAST_CHANNEL_LIB,
|
||||
crate::tsc::DENO_NET_LIB,
|
||||
crate::tsc::SHARED_GLOBALS_LIB,
|
||||
crate::tsc::WINDOW_LIB,
|
||||
];
|
||||
|
||||
if unstable {
|
||||
types.push(crate::tsc::UNSTABLE_NS_LIB);
|
||||
types.push(crate::tsc::DENO_NET_UNSTABLE_LIB);
|
||||
}
|
||||
|
||||
types.join("\n")
|
||||
|
|
|
@ -2,9 +2,9 @@
|
|||
|
||||
use crate::itest;
|
||||
use deno_core::url;
|
||||
use deno_runtime::ops::tls::rustls;
|
||||
use deno_runtime::ops::tls::webpki;
|
||||
use deno_runtime::ops::tls::TlsStream;
|
||||
use deno_runtime::deno_net::ops_tls::rustls;
|
||||
use deno_runtime::deno_net::ops_tls::webpki;
|
||||
use deno_runtime::deno_net::ops_tls::TlsStream;
|
||||
use std::fs;
|
||||
use std::io::BufReader;
|
||||
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_BROADCAST_CHANNEL_LIB: &str =
|
||||
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 =
|
||||
include_str!("dts/lib.deno.shared_globals.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);
|
||||
}
|
||||
|
||||
// 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
|
||||
window.__bootstrap = {};
|
||||
// Extra Deno.core.* exports
|
||||
|
@ -146,5 +163,7 @@
|
|||
registerErrorClass,
|
||||
handleAsyncMsgFromRust,
|
||||
syncOpsCache,
|
||||
BadResource,
|
||||
Interrupted,
|
||||
});
|
||||
})(this);
|
||||
|
|
|
@ -3,11 +3,25 @@
|
|||
|
||||
((window) => {
|
||||
const core = window.Deno.core;
|
||||
const { errors } = window.__bootstrap.errors;
|
||||
const { read, write } = window.__bootstrap.io;
|
||||
const { BadResource } = core;
|
||||
|
||||
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) {
|
||||
return core.opAsync("op_shutdown", rid);
|
||||
return core.opAsync("op_net_shutdown", rid);
|
||||
}
|
||||
|
||||
function opAccept(rid, transport) {
|
||||
|
@ -104,7 +118,7 @@
|
|||
try {
|
||||
conn = await this.accept();
|
||||
} catch (error) {
|
||||
if (error instanceof errors.BadResource) {
|
||||
if (error instanceof BadResource) {
|
||||
return { value: undefined, done: true };
|
||||
}
|
||||
throw error;
|
||||
|
@ -171,7 +185,7 @@
|
|||
try {
|
||||
yield await this.receive();
|
||||
} catch (err) {
|
||||
if (err instanceof errors.BadResource) {
|
||||
if (err instanceof BadResource) {
|
||||
break;
|
||||
}
|
||||
throw err;
|
|
@ -5,8 +5,8 @@
|
|||
const { InnerBody } = window.__bootstrap.fetchBody;
|
||||
const { Response, fromInnerRequest, toInnerResponse, newInnerRequest } =
|
||||
window.__bootstrap.fetch;
|
||||
const errors = window.__bootstrap.errors.errors;
|
||||
const core = window.Deno.core;
|
||||
const { BadResource, Interrupted } = core;
|
||||
const { ReadableStream } = window.__bootstrap.streams;
|
||||
const abortSignal = window.__bootstrap.abortSignal;
|
||||
|
||||
|
@ -42,9 +42,9 @@
|
|||
// a generic `BadResource` error. Instead store this error and replace
|
||||
// those with it.
|
||||
this[connErrorSymbol] = error;
|
||||
if (error instanceof errors.BadResource) {
|
||||
if (error instanceof BadResource) {
|
||||
return null;
|
||||
} else if (error instanceof errors.Interrupted) {
|
||||
} else if (error instanceof Interrupted) {
|
||||
return null;
|
||||
} else if (error.message.includes("connection closed")) {
|
||||
return null;
|
||||
|
@ -159,7 +159,7 @@
|
|||
], respBody instanceof Uint8Array ? respBody : null);
|
||||
} catch (error) {
|
||||
const connError = httpConn[connErrorSymbol];
|
||||
if (error instanceof errors.BadResource && connError != null) {
|
||||
if (error instanceof BadResource && connError != null) {
|
||||
// deno-lint-ignore no-ex-assign
|
||||
error = new connError.constructor(connError.message);
|
||||
}
|
||||
|
@ -192,7 +192,7 @@
|
|||
);
|
||||
} catch (error) {
|
||||
const connError = httpConn[connErrorSymbol];
|
||||
if (error instanceof errors.BadResource && connError != null) {
|
||||
if (error instanceof BadResource && connError != null) {
|
||||
// deno-lint-ignore no-ex-assign
|
||||
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.
|
||||
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_sync;
|
||||
use crate::NetPermissions;
|
||||
use deno_core::error::bad_resource;
|
||||
use deno_core::error::custom_error;
|
||||
use deno_core::error::generic_error;
|
||||
|
@ -14,7 +15,7 @@ use deno_core::op_sync;
|
|||
use deno_core::AsyncRefCell;
|
||||
use deno_core::CancelHandle;
|
||||
use deno_core::CancelTryFuture;
|
||||
use deno_core::Extension;
|
||||
use deno_core::OpPair;
|
||||
use deno_core::OpState;
|
||||
use deno_core::RcRef;
|
||||
use deno_core::Resource;
|
||||
|
@ -39,23 +40,21 @@ use trust_dns_resolver::system_conf;
|
|||
use trust_dns_resolver::AsyncResolver;
|
||||
|
||||
#[cfg(unix)]
|
||||
use super::net_unix;
|
||||
use super::ops_unix as net_unix;
|
||||
#[cfg(unix)]
|
||||
use crate::ops::io::UnixStreamResource;
|
||||
use crate::io::UnixStreamResource;
|
||||
#[cfg(unix)]
|
||||
use std::path::Path;
|
||||
|
||||
pub fn init() -> Extension {
|
||||
Extension::builder()
|
||||
.ops(vec![
|
||||
("op_accept", op_async(op_accept)),
|
||||
("op_connect", op_async(op_connect)),
|
||||
("op_listen", op_sync(op_listen)),
|
||||
("op_datagram_receive", op_async(op_datagram_receive)),
|
||||
("op_datagram_send", op_async(op_datagram_send)),
|
||||
("op_dns_resolve", op_async(op_dns_resolve)),
|
||||
])
|
||||
.build()
|
||||
pub fn init<P: NetPermissions + 'static>() -> Vec<OpPair> {
|
||||
vec![
|
||||
("op_accept", op_async(op_accept)),
|
||||
("op_connect", op_async(op_connect::<P>)),
|
||||
("op_listen", op_sync(op_listen::<P>)),
|
||||
("op_datagram_receive", op_async(op_datagram_receive)),
|
||||
("op_datagram_send", op_async(op_datagram_send::<P>)),
|
||||
("op_dns_resolve", op_async(op_dns_resolve::<P>)),
|
||||
]
|
||||
}
|
||||
|
||||
#[derive(Serialize)]
|
||||
|
@ -216,11 +215,14 @@ struct SendArgs {
|
|||
transport_args: ArgsEnum,
|
||||
}
|
||||
|
||||
async fn op_datagram_send(
|
||||
async fn op_datagram_send<NP>(
|
||||
state: Rc<RefCell<OpState>>,
|
||||
args: SendArgs,
|
||||
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.clone();
|
||||
|
||||
|
@ -232,9 +234,8 @@ async fn op_datagram_send(
|
|||
} if transport == "udp" => {
|
||||
{
|
||||
let mut s = state.borrow_mut();
|
||||
s.borrow_mut::<Permissions>()
|
||||
.net
|
||||
.check(&(&args.hostname, Some(args.port)))?;
|
||||
s.borrow_mut::<NP>()
|
||||
.check_net(&(&args.hostname, Some(args.port)))?;
|
||||
}
|
||||
let addr = resolve_addr(&args.hostname, args.port)
|
||||
.await?
|
||||
|
@ -259,7 +260,7 @@ async fn op_datagram_send(
|
|||
let address_path = Path::new(&args.path);
|
||||
{
|
||||
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
|
||||
.borrow()
|
||||
|
@ -285,11 +286,14 @@ struct ConnectArgs {
|
|||
transport_args: ArgsEnum,
|
||||
}
|
||||
|
||||
async fn op_connect(
|
||||
async fn op_connect<NP>(
|
||||
state: Rc<RefCell<OpState>>,
|
||||
args: ConnectArgs,
|
||||
_: (),
|
||||
) -> Result<OpConn, AnyError> {
|
||||
) -> Result<OpConn, AnyError>
|
||||
where
|
||||
NP: NetPermissions + 'static,
|
||||
{
|
||||
match args {
|
||||
ConnectArgs {
|
||||
transport,
|
||||
|
@ -298,9 +302,8 @@ async fn op_connect(
|
|||
{
|
||||
let mut state_ = state.borrow_mut();
|
||||
state_
|
||||
.borrow_mut::<Permissions>()
|
||||
.net
|
||||
.check(&(&args.hostname, Some(args.port)))?;
|
||||
.borrow_mut::<NP>()
|
||||
.check_net(&(&args.hostname, Some(args.port)))?;
|
||||
}
|
||||
let addr = resolve_addr(&args.hostname, args.port)
|
||||
.await?
|
||||
|
@ -335,14 +338,8 @@ async fn op_connect(
|
|||
super::check_unstable2(&state, "Deno.connect");
|
||||
{
|
||||
let mut state_ = state.borrow_mut();
|
||||
state_
|
||||
.borrow_mut::<Permissions>()
|
||||
.read
|
||||
.check(&address_path)?;
|
||||
state_
|
||||
.borrow_mut::<Permissions>()
|
||||
.write
|
||||
.check(&address_path)?;
|
||||
state_.borrow_mut::<NP>().check_read(&address_path)?;
|
||||
state_.borrow_mut::<NP>().check_write(&address_path)?;
|
||||
}
|
||||
let path = args.path;
|
||||
let unix_stream = net_unix::UnixStream::connect(Path::new(&path)).await?;
|
||||
|
@ -451,11 +448,14 @@ fn listen_udp(
|
|||
Ok((rid, local_addr))
|
||||
}
|
||||
|
||||
fn op_listen(
|
||||
fn op_listen<NP>(
|
||||
state: &mut OpState,
|
||||
args: ListenArgs,
|
||||
_: (),
|
||||
) -> Result<OpConn, AnyError> {
|
||||
) -> Result<OpConn, AnyError>
|
||||
where
|
||||
NP: NetPermissions + 'static,
|
||||
{
|
||||
match args {
|
||||
ListenArgs {
|
||||
transport,
|
||||
|
@ -466,9 +466,8 @@ fn op_listen(
|
|||
super::check_unstable(state, "Deno.listenDatagram");
|
||||
}
|
||||
state
|
||||
.borrow_mut::<Permissions>()
|
||||
.net
|
||||
.check(&(&args.hostname, Some(args.port)))?;
|
||||
.borrow_mut::<NP>()
|
||||
.check_net(&(&args.hostname, Some(args.port)))?;
|
||||
}
|
||||
let addr = resolve_addr_sync(&args.hostname, args.port)?
|
||||
.next()
|
||||
|
@ -512,9 +511,9 @@ fn op_listen(
|
|||
if transport == "unixpacket" {
|
||||
super::check_unstable(state, "Deno.listenDatagram");
|
||||
}
|
||||
let permissions = state.borrow_mut::<Permissions>();
|
||||
permissions.read.check(&address_path)?;
|
||||
permissions.write.check(&address_path)?;
|
||||
let permissions = state.borrow_mut::<NP>();
|
||||
permissions.check_read(&address_path)?;
|
||||
permissions.check_write(&address_path)?;
|
||||
}
|
||||
let (rid, local_addr) = if transport == "unix" {
|
||||
net_unix::listen_unix(state, &address_path)?
|
||||
|
@ -592,11 +591,14 @@ pub struct NameServer {
|
|||
port: u16,
|
||||
}
|
||||
|
||||
async fn op_dns_resolve(
|
||||
async fn op_dns_resolve<NP>(
|
||||
state: Rc<RefCell<OpState>>,
|
||||
args: ResolveAddrArgs,
|
||||
_: (),
|
||||
) -> Result<Vec<DnsReturnRecord>, AnyError> {
|
||||
) -> Result<Vec<DnsReturnRecord>, AnyError>
|
||||
where
|
||||
NP: NetPermissions + 'static,
|
||||
{
|
||||
let ResolveAddrArgs {
|
||||
query,
|
||||
record_type,
|
||||
|
@ -621,14 +623,14 @@ async fn op_dns_resolve(
|
|||
|
||||
{
|
||||
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.
|
||||
for ns in config.name_servers() {
|
||||
let socker_addr = &ns.socket_addr;
|
||||
let ip = socker_addr.ip().to_string();
|
||||
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.
|
||||
|
||||
use crate::ops::io::TcpStreamResource;
|
||||
use crate::ops::io::TlsStreamResource;
|
||||
use crate::ops::tls::TlsStream;
|
||||
use crate::io::TcpStreamResource;
|
||||
use crate::io::TlsStreamResource;
|
||||
use crate::ops_tls::TlsStream;
|
||||
use deno_core::error::bad_resource_id;
|
||||
use deno_core::error::null_opbuf;
|
||||
use deno_core::error::type_error;
|
||||
|
@ -17,7 +17,7 @@ use deno_core::AsyncRefCell;
|
|||
use deno_core::ByteString;
|
||||
use deno_core::CancelHandle;
|
||||
use deno_core::CancelTryFuture;
|
||||
use deno_core::Extension;
|
||||
use deno_core::OpPair;
|
||||
use deno_core::OpState;
|
||||
use deno_core::RcRef;
|
||||
use deno_core::Resource;
|
||||
|
@ -46,17 +46,15 @@ use tokio::net::TcpStream;
|
|||
use tokio::sync::oneshot;
|
||||
use tokio_util::io::StreamReader;
|
||||
|
||||
pub fn init() -> Extension {
|
||||
Extension::builder()
|
||||
.ops(vec![
|
||||
("op_http_start", op_sync(op_http_start)),
|
||||
("op_http_request_next", op_async(op_http_request_next)),
|
||||
("op_http_request_read", op_async(op_http_request_read)),
|
||||
("op_http_response", op_async(op_http_response)),
|
||||
("op_http_response_write", op_async(op_http_response_write)),
|
||||
("op_http_response_close", op_async(op_http_response_close)),
|
||||
])
|
||||
.build()
|
||||
pub fn init() -> Vec<OpPair> {
|
||||
vec![
|
||||
("op_http_start", op_sync(op_http_start)),
|
||||
("op_http_request_next", op_async(op_http_request_next)),
|
||||
("op_http_request_read", op_async(op_http_request_read)),
|
||||
("op_http_response", op_async(op_http_response)),
|
||||
("op_http_response_write", op_async(op_http_response_write)),
|
||||
("op_http_response_close", op_async(op_http_response_close)),
|
||||
]
|
||||
}
|
||||
|
||||
struct ServiceInner {
|
|
@ -3,14 +3,14 @@
|
|||
pub use rustls;
|
||||
pub use webpki;
|
||||
|
||||
use crate::ops::io::TcpStreamResource;
|
||||
use crate::ops::io::TlsStreamResource;
|
||||
use crate::ops::net::IpAddr;
|
||||
use crate::ops::net::OpAddr;
|
||||
use crate::ops::net::OpConn;
|
||||
use crate::permissions::Permissions;
|
||||
use crate::io::TcpStreamResource;
|
||||
use crate::io::TlsStreamResource;
|
||||
use crate::ops::IpAddr;
|
||||
use crate::ops::OpAddr;
|
||||
use crate::ops::OpConn;
|
||||
use crate::resolve_addr::resolve_addr;
|
||||
use crate::resolve_addr::resolve_addr_sync;
|
||||
use crate::NetPermissions;
|
||||
use deno_core::error::bad_resource;
|
||||
use deno_core::error::bad_resource_id;
|
||||
use deno_core::error::custom_error;
|
||||
|
@ -31,7 +31,7 @@ use deno_core::op_sync;
|
|||
use deno_core::AsyncRefCell;
|
||||
use deno_core::CancelHandle;
|
||||
use deno_core::CancelTryFuture;
|
||||
use deno_core::Extension;
|
||||
use deno_core::OpPair;
|
||||
use deno_core::OpState;
|
||||
use deno_core::RcRef;
|
||||
use deno_core::Resource;
|
||||
|
@ -662,15 +662,13 @@ impl Write for ImplementWriteTrait<'_, TcpStream> {
|
|||
}
|
||||
}
|
||||
|
||||
pub fn init() -> Extension {
|
||||
Extension::builder()
|
||||
.ops(vec![
|
||||
("op_start_tls", op_async(op_start_tls)),
|
||||
("op_connect_tls", op_async(op_connect_tls)),
|
||||
("op_listen_tls", op_sync(op_listen_tls)),
|
||||
("op_accept_tls", op_async(op_accept_tls)),
|
||||
])
|
||||
.build()
|
||||
pub fn init<P: NetPermissions + 'static>() -> Vec<OpPair> {
|
||||
vec![
|
||||
("op_start_tls", op_async(op_start_tls::<P>)),
|
||||
("op_connect_tls", op_async(op_connect_tls::<P>)),
|
||||
("op_listen_tls", op_sync(op_listen_tls::<P>)),
|
||||
("op_accept_tls", op_async(op_accept_tls)),
|
||||
]
|
||||
}
|
||||
|
||||
#[derive(Deserialize)]
|
||||
|
@ -690,11 +688,14 @@ struct StartTlsArgs {
|
|||
hostname: String,
|
||||
}
|
||||
|
||||
async fn op_start_tls(
|
||||
async fn op_start_tls<NP>(
|
||||
state: Rc<RefCell<OpState>>,
|
||||
args: StartTlsArgs,
|
||||
_: (),
|
||||
) -> Result<OpConn, AnyError> {
|
||||
) -> Result<OpConn, AnyError>
|
||||
where
|
||||
NP: NetPermissions + 'static,
|
||||
{
|
||||
let rid = args.rid;
|
||||
let hostname = match &*args.hostname {
|
||||
"" => "localhost",
|
||||
|
@ -705,10 +706,10 @@ async fn op_start_tls(
|
|||
{
|
||||
super::check_unstable2(&state, "Deno.startTls");
|
||||
let mut s = state.borrow_mut();
|
||||
let permissions = s.borrow_mut::<Permissions>();
|
||||
permissions.net.check(&(hostname, Some(0)))?;
|
||||
let permissions = s.borrow_mut::<NP>();
|
||||
permissions.check_net(&(hostname, Some(0)))?;
|
||||
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>>,
|
||||
args: ConnectTlsArgs,
|
||||
_: (),
|
||||
) -> Result<OpConn, AnyError> {
|
||||
) -> Result<OpConn, AnyError>
|
||||
where
|
||||
NP: NetPermissions + 'static,
|
||||
{
|
||||
assert_eq!(args.transport, "tcp");
|
||||
let hostname = match &*args.hostname {
|
||||
"" => "localhost",
|
||||
|
@ -778,10 +782,10 @@ async fn op_connect_tls(
|
|||
|
||||
{
|
||||
let mut s = state.borrow_mut();
|
||||
let permissions = s.borrow_mut::<Permissions>();
|
||||
permissions.net.check(&(hostname, Some(port)))?;
|
||||
let permissions = s.borrow_mut::<NP>();
|
||||
permissions.check_net(&(hostname, Some(port)))?;
|
||||
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>>,
|
||||
}
|
||||
|
||||
fn op_listen_tls(
|
||||
fn op_listen_tls<NP>(
|
||||
state: &mut OpState,
|
||||
args: ListenTlsArgs,
|
||||
_: (),
|
||||
) -> Result<OpConn, AnyError> {
|
||||
) -> Result<OpConn, AnyError>
|
||||
where
|
||||
NP: NetPermissions + 'static,
|
||||
{
|
||||
assert_eq!(args.transport, "tcp");
|
||||
let hostname = &*args.hostname;
|
||||
let port = args.port;
|
||||
|
@ -924,10 +931,10 @@ fn op_listen_tls(
|
|||
let key_file = &*args.key_file;
|
||||
|
||||
{
|
||||
let permissions = state.borrow_mut::<Permissions>();
|
||||
permissions.net.check(&(hostname, Some(port)))?;
|
||||
permissions.read.check(Path::new(cert_file))?;
|
||||
permissions.read.check(Path::new(key_file))?;
|
||||
let permissions = state.borrow_mut::<NP>();
|
||||
permissions.check_net(&(hostname, Some(port)))?;
|
||||
permissions.check_read(Path::new(cert_file))?;
|
||||
permissions.check_read(Path::new(key_file))?;
|
||||
}
|
||||
|
||||
let mut tls_config = ServerConfig::new(NoClientAuth::new());
|
|
@ -1,12 +1,11 @@
|
|||
// Copyright 2018-2021 the Deno authors. All rights reserved. MIT license.
|
||||
|
||||
use super::utils::into_string;
|
||||
use crate::ops::io::UnixStreamResource;
|
||||
use crate::ops::net::AcceptArgs;
|
||||
use crate::ops::net::OpAddr;
|
||||
use crate::ops::net::OpConn;
|
||||
use crate::ops::net::OpPacket;
|
||||
use crate::ops::net::ReceiveArgs;
|
||||
use crate::io::UnixStreamResource;
|
||||
use crate::ops::AcceptArgs;
|
||||
use crate::ops::OpAddr;
|
||||
use crate::ops::OpConn;
|
||||
use crate::ops::OpPacket;
|
||||
use crate::ops::ReceiveArgs;
|
||||
use deno_core::error::bad_resource;
|
||||
use deno_core::error::custom_error;
|
||||
use deno_core::error::null_opbuf;
|
||||
|
@ -29,6 +28,14 @@ use tokio::net::UnixDatagram;
|
|||
use tokio::net::UnixListener;
|
||||
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 {
|
||||
listener: AsyncRefCell<UnixListener>,
|
||||
cancel: CancelHandle,
|
|
@ -23,6 +23,7 @@ deno_console = { version = "0.10.0", path = "../extensions/console" }
|
|||
deno_core = { version = "0.92.0", path = "../core" }
|
||||
deno_crypto = { version = "0.24.0", path = "../extensions/crypto" }
|
||||
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_url = { version = "0.10.0", path = "../extensions/url" }
|
||||
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_crypto = { version = "0.24.0", path = "../extensions/crypto" }
|
||||
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_url = { version = "0.10.0", path = "../extensions/url" }
|
||||
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" }
|
||||
|
||||
atty = "0.2.14"
|
||||
bytes = "1"
|
||||
dlopen = "0.1.8"
|
||||
encoding_rs = "0.8.28"
|
||||
filetime = "0.2.14"
|
||||
|
@ -64,17 +65,11 @@ notify = "5.0.0-pre.7"
|
|||
percent-encoding = "2.1.0"
|
||||
regex = "1.4.3"
|
||||
ring = "0.16.20"
|
||||
rustls = "0.19.0"
|
||||
serde = { version = "1.0.125", features = ["derive"] }
|
||||
sys-info = "0.9.0"
|
||||
termcolor = "1.1.2"
|
||||
tokio = { version = "1.7.1", features = ["full"] }
|
||||
tokio-util = { version = "0.6", features = ["io"] }
|
||||
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]
|
||||
fwdansi = "1.1.0"
|
||||
|
|
|
@ -59,6 +59,7 @@ fn create_runtime_snapshot(snapshot_path: &Path, files: Vec<PathBuf>) {
|
|||
deno_broadcast_channel::InMemoryBroadcastChannel::default(),
|
||||
false, // No --unstable.
|
||||
),
|
||||
deno_net::init::<deno_net::NoNetPermissions>(false), // No --unstable.
|
||||
];
|
||||
|
||||
let js_runtime = JsRuntime::new(RuntimeOptions {
|
||||
|
|
|
@ -2,6 +2,9 @@
|
|||
"use strict";
|
||||
|
||||
((window) => {
|
||||
const core = window.Deno.core;
|
||||
const { BadResource, Interrupted } = core;
|
||||
|
||||
class NotFound extends Error {
|
||||
constructor(msg) {
|
||||
super(msg);
|
||||
|
@ -86,13 +89,6 @@
|
|||
}
|
||||
}
|
||||
|
||||
class Interrupted extends Error {
|
||||
constructor(msg) {
|
||||
super(msg);
|
||||
this.name = "Interrupted";
|
||||
}
|
||||
}
|
||||
|
||||
class WriteZero extends Error {
|
||||
constructor(msg) {
|
||||
super(msg);
|
||||
|
@ -107,13 +103,6 @@
|
|||
}
|
||||
}
|
||||
|
||||
class BadResource extends Error {
|
||||
constructor(msg) {
|
||||
super(msg);
|
||||
this.name = "BadResource";
|
||||
}
|
||||
}
|
||||
|
||||
class Http extends Error {
|
||||
constructor(msg) {
|
||||
super(msg);
|
||||
|
|
|
@ -4,6 +4,7 @@ pub use deno_broadcast_channel;
|
|||
pub use deno_console;
|
||||
pub use deno_crypto;
|
||||
pub use deno_fetch;
|
||||
pub use deno_net;
|
||||
pub use deno_timers;
|
||||
pub use deno_url;
|
||||
pub use deno_web;
|
||||
|
@ -20,7 +21,6 @@ pub mod js;
|
|||
pub mod metrics;
|
||||
pub mod ops;
|
||||
pub mod permissions;
|
||||
pub mod resolve_addr;
|
||||
pub mod tokio_util;
|
||||
pub mod web_worker;
|
||||
pub mod worker;
|
||||
|
|
|
@ -1,6 +1,5 @@
|
|||
// 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::resource_unavailable;
|
||||
use deno_core::error::AnyError;
|
||||
|
@ -17,6 +16,9 @@ use deno_core::RcRef;
|
|||
use deno_core::Resource;
|
||||
use deno_core::ResourceId;
|
||||
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::cell::RefCell;
|
||||
use std::io::Read;
|
||||
|
@ -26,13 +28,10 @@ use tokio::io::AsyncRead;
|
|||
use tokio::io::AsyncReadExt;
|
||||
use tokio::io::AsyncWrite;
|
||||
use tokio::io::AsyncWriteExt;
|
||||
use tokio::net::tcp;
|
||||
use tokio::process;
|
||||
|
||||
#[cfg(unix)]
|
||||
use std::os::unix::io::FromRawFd;
|
||||
#[cfg(unix)]
|
||||
use tokio::net::unix;
|
||||
|
||||
#[cfg(windows)]
|
||||
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>;
|
||||
|
||||
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)]
|
||||
pub struct StdFileResource {
|
||||
pub fs_file:
|
||||
|
|
|
@ -2,18 +2,13 @@
|
|||
|
||||
pub mod fs;
|
||||
pub mod fs_events;
|
||||
pub mod http;
|
||||
pub mod io;
|
||||
pub mod net;
|
||||
#[cfg(unix)]
|
||||
mod net_unix;
|
||||
pub mod os;
|
||||
pub mod permissions;
|
||||
pub mod plugin;
|
||||
pub mod process;
|
||||
pub mod runtime;
|
||||
pub mod signal;
|
||||
pub mod tls;
|
||||
pub mod tty;
|
||||
mod utils;
|
||||
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 {
|
||||
fn check_net_url(&mut self, url: &url::Url) -> Result<(), AnyError> {
|
||||
self.net.check_url(url)
|
||||
|
|
|
@ -330,14 +330,12 @@ impl WebWorker {
|
|||
vec![
|
||||
ops::fs_events::init(),
|
||||
ops::fs::init(),
|
||||
ops::net::init(),
|
||||
deno_net::init::<Permissions>(options.unstable),
|
||||
ops::os::init(),
|
||||
ops::http::init(),
|
||||
ops::permissions::init(),
|
||||
ops::plugin::init(),
|
||||
ops::process::init(),
|
||||
ops::signal::init(),
|
||||
ops::tls::init(),
|
||||
ops::tty::init(),
|
||||
ops::io::init_stdio(),
|
||||
]
|
||||
|
|
|
@ -120,16 +120,14 @@ impl MainWorker {
|
|||
ops::worker_host::init(options.create_web_worker_cb.clone()),
|
||||
ops::fs_events::init(),
|
||||
ops::fs::init(),
|
||||
ops::http::init(),
|
||||
ops::io::init(),
|
||||
ops::io::init_stdio(),
|
||||
ops::net::init(),
|
||||
deno_net::init::<Permissions>(options.unstable),
|
||||
ops::os::init(),
|
||||
ops::permissions::init(),
|
||||
ops::plugin::init(),
|
||||
ops::process::init(),
|
||||
ops::signal::init(),
|
||||
ops::tls::init(),
|
||||
ops::tty::init(),
|
||||
// Permissions ext (worker specific state)
|
||||
perm_ext,
|
||||
|
|
Loading…
Reference in a new issue