mirror of
https://github.com/denoland/deno.git
synced 2025-03-03 09:31:22 -05:00
stabilize net Addr (#3709)
Co-authored-by: xiaoxintang <15707971810@163.com>
This commit is contained in:
parent
34b99fec8e
commit
23e67eb515
7 changed files with 115 additions and 86 deletions
18
cli/js/lib.deno_runtime.d.ts
vendored
18
cli/js/lib.deno_runtime.d.ts
vendored
|
@ -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<Conn>;
|
||||
}
|
||||
|
||||
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.)
|
||||
|
|
|
@ -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<Conn> {
|
|||
close(): void;
|
||||
|
||||
/** Return the address of the `Listener`. */
|
||||
addr(): Addr;
|
||||
addr: Addr;
|
||||
|
||||
[Symbol.asyncIterator](): AsyncIterator<Conn>;
|
||||
}
|
||||
|
@ -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<number> {
|
||||
|
@ -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<IteratorResult<Conn>> {
|
||||
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<Conn> {
|
||||
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!);
|
||||
}
|
||||
|
|
|
@ -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<void> {
|
|||
listener.accept().then(
|
||||
async (conn): Promise<void> => {
|
||||
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);
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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,
|
||||
},
|
||||
})))
|
||||
}
|
||||
|
|
|
@ -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<String>,
|
||||
|
@ -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()
|
||||
}
|
||||
}))
|
||||
};
|
||||
|
||||
|
|
|
@ -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<number | Deno.EOF> => {
|
||||
return 0;
|
||||
},
|
||||
write: async (): Promise<number> => {
|
||||
return -1;
|
||||
},
|
||||
close: (): void => {}
|
||||
};
|
||||
|
||||
const responseTests: ResponseTest[] = [
|
||||
// Default response
|
||||
{
|
||||
|
@ -75,20 +98,7 @@ test(async function responseWrite(): Promise<void> {
|
|||
const request = new ServerRequest();
|
||||
request.w = bufw;
|
||||
|
||||
request.conn = {
|
||||
localAddr: "",
|
||||
remoteAddr: "",
|
||||
rid: -1,
|
||||
closeRead: (): void => {},
|
||||
closeWrite: (): void => {},
|
||||
read: async (): Promise<number | Deno.EOF> => {
|
||||
return 0;
|
||||
},
|
||||
write: async (): Promise<number> => {
|
||||
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<void> {
|
|||
assertEquals(r.more, false);
|
||||
});
|
||||
|
||||
const mockConn = {
|
||||
localAddr: "",
|
||||
remoteAddr: "",
|
||||
rid: -1,
|
||||
closeRead: (): void => {},
|
||||
closeWrite: (): void => {},
|
||||
read: async (): Promise<number | Deno.EOF> => {
|
||||
return 0;
|
||||
},
|
||||
write: async (): Promise<number> => {
|
||||
return -1;
|
||||
},
|
||||
close: (): void => {}
|
||||
};
|
||||
|
||||
test(async function readRequestError(): Promise<void> {
|
||||
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<void> {
|
|||
// 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;
|
||||
}
|
||||
|
|
Loading…
Add table
Reference in a new issue