From 23e67eb5153bd26dbae471b27dc6a21a6d283b0b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bartek=20Iwa=C5=84czuk?= Date: Sat, 18 Jan 2020 21:49:55 +0100 Subject: [PATCH] stabilize net Addr (#3709) Co-authored-by: xiaoxintang <15707971810@163.com> --- cli/js/lib.deno_runtime.d.ts | 18 +++++------- cli/js/net.ts | 39 ++++++++++-------------- cli/js/net_test.ts | 14 ++++----- cli/js/tls.ts | 3 +- cli/ops/net.rs | 38 +++++++++++++++++++----- cli/ops/tls.rs | 32 ++++++++++++++++---- std/http/server_test.ts | 57 ++++++++++++++++-------------------- 7 files changed, 115 insertions(+), 86 deletions(-) diff --git a/cli/js/lib.deno_runtime.d.ts b/cli/js/lib.deno_runtime.d.ts index c4055bc35338e..6e3e2384a0d10 100644 --- a/cli/js/lib.deno_runtime.d.ts +++ b/cli/js/lib.deno_runtime.d.ts @@ -1307,8 +1307,8 @@ declare namespace Deno { interface Addr { transport: Transport; - /** UNSTABLE: Address is unstable because inconsistent with ConnectOptions. */ - address: string; + hostname: string; + port: number; } /** UNSTABLE: Maybe remove ShutdownMode entirely. */ @@ -1342,21 +1342,19 @@ declare namespace Deno { */ close(): void; /** Return the address of the `Listener`. */ - addr(): Addr; + addr: Addr; [Symbol.asyncIterator](): AsyncIterator; } export interface Conn extends Reader, Writer, Closer { - /** UNSTABLE: return Addr? - * + /** * The local address of the connection. */ - localAddr: string; - /** UNSTABLE: return Addr? - * + localAddr: Addr; + /** * The remote address of the connection. */ - remoteAddr: string; + remoteAddr: Addr; /** The resource ID of the connection. */ rid: number; /** Shuts down (`shutdown(2)`) the reading side of the TCP connection. Most @@ -1426,7 +1424,7 @@ declare namespace Deno { } /** - * Dial connects to the address on the named transport. + * Connects to the address on the named transport. * * @param options * @param options.port The port to connect to. (Required.) diff --git a/cli/js/net.ts b/cli/js/net.ts index 3744541367043..a89468f02f226 100644 --- a/cli/js/net.ts +++ b/cli/js/net.ts @@ -8,11 +8,10 @@ export type Transport = "tcp"; // TODO support other types: // export type Transport = "tcp" | "tcp4" | "tcp6" | "unix" | "unixpacket"; -// TODO(ry) Replace 'address' with 'hostname' and 'port', similar to ConnectOptions -// and ListenOptions. export interface Addr { transport: Transport; - address: string; + hostname: string; + port: number; } /** A Listener is a generic transport listener for stream-oriented protocols. */ @@ -26,7 +25,7 @@ export interface Listener extends AsyncIterator { close(): void; /** Return the address of the `Listener`. */ - addr(): Addr; + addr: Addr; [Symbol.asyncIterator](): AsyncIterator; } @@ -54,8 +53,8 @@ export function shutdown(rid: number, how: ShutdownMode): void { export class ConnImpl implements Conn { constructor( readonly rid: number, - readonly remoteAddr: string, - readonly localAddr: string + readonly remoteAddr: Addr, + readonly localAddr: Addr ) {} write(p: Uint8Array): Promise { @@ -88,8 +87,7 @@ export class ConnImpl implements Conn { export class ListenerImpl implements Listener { constructor( readonly rid: number, - private transport: Transport, - private localAddr: string, + public addr: Addr, private closing: boolean = false ) {} @@ -103,13 +101,6 @@ export class ListenerImpl implements Listener { close(this.rid); } - addr(): Addr { - return { - transport: this.transport, - address: this.localAddr - }; - } - async next(): Promise> { if (this.closing) { return { value: undefined, done: true }; @@ -134,9 +125,9 @@ export class ListenerImpl implements Listener { export interface Conn extends Reader, Writer, Closer { /** The local address of the connection. */ - localAddr: string; + localAddr: Addr; /** The remote address of the connection. */ - remoteAddr: string; + remoteAddr: Addr; /** The resource ID of the connection. */ rid: number; /** Shuts down (`shutdown(2)`) the reading side of the TCP connection. Most @@ -175,12 +166,13 @@ export interface ListenOptions { export function listen(options: ListenOptions): Listener { const hostname = options.hostname || "0.0.0.0"; const transport = options.transport || "tcp"; + const res = sendSync(dispatch.OP_LISTEN, { hostname, port: options.port, transport }); - return new ListenerImpl(res.rid, transport, res.localAddr); + return new ListenerImpl(res.rid, res.localAddr); } export interface ConnectOptions { @@ -189,7 +181,9 @@ export interface ConnectOptions { transport?: Transport; } -/** Dial connects to the address on the named transport. +const connectDefaults = { hostname: "127.0.0.1", transport: "tcp" }; + +/** Connects to the address on the named transport. * * @param options * @param options.port The port to connect to. (Required.) @@ -207,10 +201,7 @@ export interface ConnectOptions { * connect({ hostname: "golang.org", port: 80, transport: "tcp" }) */ export async function connect(options: ConnectOptions): Promise { - const res = await sendAsync(dispatch.OP_CONNECT, { - hostname: options.hostname || "127.0.0.1", - port: options.port, - transport: options.transport || "tcp" - }); + options = Object.assign(connectDefaults, options); + const res = await sendAsync(dispatch.OP_CONNECT, options); return new ConnImpl(res.rid, res.remoteAddr!, res.localAddr!); } diff --git a/cli/js/net_test.ts b/cli/js/net_test.ts index ec395bc1db0bc..e4d0be81f9c96 100644 --- a/cli/js/net_test.ts +++ b/cli/js/net_test.ts @@ -3,11 +3,9 @@ import { testPerm, assert, assertEquals } from "./test_util.ts"; testPerm({ net: true }, function netListenClose(): void { const listener = Deno.listen({ hostname: "127.0.0.1", port: 4500 }); - const addr = listener.addr(); - assertEquals(addr.transport, "tcp"); - // TODO(ry) Replace 'address' with 'hostname' and 'port', similar to - // ConnectOptions and ListenOptions. - assertEquals(addr.address, "127.0.0.1:4500"); + assertEquals(listener.addr.transport, "tcp"); + assertEquals(listener.addr.hostname, "127.0.0.1"); + assertEquals(listener.addr.port, 4500); listener.close(); }); @@ -52,13 +50,15 @@ testPerm({ net: true }, async function netDialListen(): Promise { listener.accept().then( async (conn): Promise => { assert(conn.remoteAddr != null); - assertEquals(conn.localAddr, "127.0.0.1:4500"); + assertEquals(conn.localAddr.hostname, "127.0.0.1"); + assertEquals(conn.localAddr.port, 4500); await conn.write(new Uint8Array([1, 2, 3])); conn.close(); } ); const conn = await Deno.connect({ hostname: "127.0.0.1", port: 4500 }); - assertEquals(conn.remoteAddr, "127.0.0.1:4500"); + assertEquals(conn.remoteAddr.hostname, "127.0.0.1"); + assertEquals(conn.remoteAddr.port, 4500); assert(conn.localAddr != null); const buf = new Uint8Array(1024); const readResult = await conn.read(buf); diff --git a/cli/js/tls.ts b/cli/js/tls.ts index 4dfb32e312c45..b8815831b448a 100644 --- a/cli/js/tls.ts +++ b/cli/js/tls.ts @@ -6,6 +6,7 @@ import { Listener, Transport, Conn, ConnImpl, ListenerImpl } from "./net.ts"; // TODO(ry) There are many configuration options to add... // https://docs.rs/rustls/0.16.0/rustls/struct.ClientConfig.html interface ConnectTLSOptions { + transport?: Transport; port: number; hostname?: string; certFile?: string; @@ -59,5 +60,5 @@ export function listenTLS(options: ListenTLSOptions): Listener { certFile: options.certFile, keyFile: options.keyFile }); - return new TLSListenerImpl(res.rid, transport, res.localAddr); + return new TLSListenerImpl(res.rid, res.localAddr); } diff --git a/cli/ops/net.rs b/cli/ops/net.rs index f337a28d808f6..836ec2e8d3915 100644 --- a/cli/ops/net.rs +++ b/cli/ops/net.rs @@ -117,8 +117,16 @@ fn op_accept( table.add("tcpStream", Box::new(StreamResource::TcpStream(tcp_stream))); Ok(json!({ "rid": rid, - "localAddr": local_addr.to_string(), - "remoteAddr": remote_addr.to_string(), + "localAddr": { + "hostname": local_addr.ip().to_string(), + "port": local_addr.port(), + "transport": "tcp", + }, + "remoteAddr": { + "hostname": remote_addr.ip().to_string(), + "port": remote_addr.port(), + "transport": "tcp", + } })) }; @@ -152,8 +160,16 @@ fn op_connect( table.add("tcpStream", Box::new(StreamResource::TcpStream(tcp_stream))); Ok(json!({ "rid": rid, - "localAddr": local_addr.to_string(), - "remoteAddr": remote_addr.to_string(), + "localAddr": { + "hostname": local_addr.ip().to_string(), + "port": local_addr.port(), + "transport": args.transport, + }, + "remoteAddr": { + "hostname": remote_addr.ip().to_string(), + "port": remote_addr.port(), + "transport": args.transport, + } })) }; @@ -272,7 +288,6 @@ fn op_listen( futures::executor::block_on(resolve_addr(&args.hostname, args.port))?; let listener = futures::executor::block_on(TcpListener::bind(&addr))?; let local_addr = listener.local_addr()?; - let local_addr_str = local_addr.to_string(); let listener_resource = TcpListenerResource { listener, waker: None, @@ -280,10 +295,19 @@ fn op_listen( }; let mut table = state.lock_resource_table(); let rid = table.add("tcpListener", Box::new(listener_resource)); - debug!("New listener {} {}", rid, local_addr_str); + debug!( + "New listener {} {}:{}", + rid, + local_addr.ip().to_string(), + local_addr.port() + ); Ok(JsonOp::Sync(json!({ "rid": rid, - "localAddr": local_addr_str, + "localAddr": { + "hostname": local_addr.ip().to_string(), + "port": local_addr.port(), + "transport": args.transport, + }, }))) } diff --git a/cli/ops/tls.rs b/cli/ops/tls.rs index fc2dec0d19308..cb0ae2ecbff3a 100644 --- a/cli/ops/tls.rs +++ b/cli/ops/tls.rs @@ -53,6 +53,7 @@ pub fn init(i: &mut Isolate, s: &ThreadSafeState) { #[derive(Deserialize)] #[serde(rename_all = "camelCase")] struct ConnectTLSArgs { + transport: String, hostname: String, port: u16, cert_file: Option, @@ -101,8 +102,16 @@ pub fn op_connect_tls( ); Ok(json!({ "rid": rid, - "localAddr": local_addr.to_string(), - "remoteAddr": remote_addr.to_string(), + "localAddr": { + "hostname": local_addr.ip().to_string(), + "port": local_addr.port(), + "transport": args.transport, + }, + "remoteAddr": { + "hostname": remote_addr.ip().to_string(), + "port": remote_addr.port(), + "transport": args.transport, + } })) }; @@ -257,7 +266,6 @@ fn op_listen_tls( futures::executor::block_on(resolve_addr(&args.hostname, args.port))?; let listener = futures::executor::block_on(TcpListener::bind(&addr))?; let local_addr = listener.local_addr()?; - let local_addr_str = local_addr.to_string(); let tls_listener_resource = TlsListenerResource { listener, tls_acceptor, @@ -269,7 +277,11 @@ fn op_listen_tls( Ok(JsonOp::Sync(json!({ "rid": rid, - "localAddr": local_addr_str + "localAddr": { + "hostname": local_addr.ip().to_string(), + "port": local_addr.port(), + "transport": args.transport, + }, }))) } @@ -371,8 +383,16 @@ fn op_accept_tls( }; Ok(json!({ "rid": rid, - "localAddr": local_addr.to_string(), - "remoteAddr": remote_addr.to_string(), + "localAddr": { + "transport": "tcp", + "hostname": local_addr.ip().to_string(), + "port": local_addr.port() + }, + "remoteAddr": { + "transport": "tcp", + "hostname": remote_addr.ip().to_string(), + "port": remote_addr.port() + } })) }; diff --git a/std/http/server_test.ts b/std/http/server_test.ts index aee9db0ff3404..a4bc58ad1a239 100644 --- a/std/http/server_test.ts +++ b/std/http/server_test.ts @@ -41,6 +41,29 @@ const dec = new TextDecoder(); type Handler = () => void; +const mockConn = { + localAddr: { + transport: "tcp", + hostname: "", + port: 0 + }, + remoteAddr: { + transport: "tcp", + hostname: "", + port: 0 + }, + rid: -1, + closeRead: (): void => {}, + closeWrite: (): void => {}, + read: async (): Promise => { + return 0; + }, + write: async (): Promise => { + return -1; + }, + close: (): void => {} +}; + const responseTests: ResponseTest[] = [ // Default response { @@ -75,20 +98,7 @@ test(async function responseWrite(): Promise { const request = new ServerRequest(); request.w = bufw; - request.conn = { - localAddr: "", - remoteAddr: "", - rid: -1, - closeRead: (): void => {}, - closeWrite: (): void => {}, - read: async (): Promise => { - return 0; - }, - write: async (): Promise => { - return -1; - }, - close: (): void => {} - }; + request.conn = mockConn as Deno.Conn; await request.respond(testCase.response); assertEquals(buf.toString(), testCase.raw); @@ -416,21 +426,6 @@ test(async function writeStringReaderResponse(): Promise { assertEquals(r.more, false); }); -const mockConn = { - localAddr: "", - remoteAddr: "", - rid: -1, - closeRead: (): void => {}, - closeWrite: (): void => {}, - read: async (): Promise => { - return 0; - }, - write: async (): Promise => { - return -1; - }, - close: (): void => {} -}; - test(async function readRequestError(): Promise { const input = `GET / HTTP/1.1 malformedHeader @@ -438,7 +433,7 @@ malformedHeader const reader = new BufReader(new StringReader(input)); let err; try { - await readRequest(mockConn, reader); + await readRequest(mockConn as Deno.Conn, reader); } catch (e) { err = e; } @@ -517,7 +512,7 @@ test(async function testReadRequestError(): Promise { // eslint-disable-next-line @typescript-eslint/no-explicit-any let req: any; try { - req = await readRequest(mockConn, reader); + req = await readRequest(mockConn as Deno.Conn, reader); } catch (e) { err = e; }