refactor: factor out datagram from Deno.listen(), make it unstable (#4968)

This commit changes Deno.listen() API by factoring out datagram listeners to Deno.listenDatagram(). New Deno.listenDatagram() is unstable.
This commit is contained in:
Bartek Iwańczuk 2020-04-28 21:46:39 +02:00 committed by GitHub
parent ea28a088a4
commit 1b6181e434
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
5 changed files with 69 additions and 38 deletions

View file

@ -64,6 +64,7 @@ export { mkdirSync, mkdir, MkdirOptions } from "./ops/fs/mkdir.ts";
export { export {
connect, connect,
listen, listen,
listenDatagram,
DatagramConn, DatagramConn,
Listener, Listener,
Conn, Conn,

View file

@ -1920,9 +1920,7 @@ declare namespace Deno {
/** A Path to the Unix Socket. */ /** A Path to the Unix Socket. */
path: string; path: string;
} }
/** **UNSTABLE**: new API, yet to be vetted. /** Listen announces on the local transport address.
*
* Listen announces on the local transport address.
* *
* const listener1 = Deno.listen({ port: 80 }) * const listener1 = Deno.listen({ port: 80 })
* const listener2 = Deno.listen({ hostname: "192.0.2.1", port: 80 }) * const listener2 = Deno.listen({ hostname: "192.0.2.1", port: 80 })
@ -1933,9 +1931,7 @@ declare namespace Deno {
export function listen( export function listen(
options: ListenOptions & { transport?: "tcp" } options: ListenOptions & { transport?: "tcp" }
): Listener; ): Listener;
/** **UNSTABLE**: new API, yet to be vetted. /** Listen announces on the local transport address.
*
* Listen announces on the local transport address.
* *
* const listener = Deno.listen({ path: "/foo/bar.sock", transport: "unix" }) * const listener = Deno.listen({ path: "/foo/bar.sock", transport: "unix" })
* *
@ -1943,25 +1939,37 @@ declare namespace Deno {
export function listen( export function listen(
options: UnixListenOptions & { transport: "unix" } options: UnixListenOptions & { transport: "unix" }
): Listener; ): Listener;
/** **UNSTABLE**: new API, yet to be vetted.
/** **UNSTABLE**: new API
* *
* Listen announces on the local transport address. * Listen announces on the local transport address.
* *
* const listener1 = Deno.listen({ port: 80, transport: "udp" }) * const listener1 = Deno.listenDatagram({
* const listener2 = Deno.listen({ hostname: "golang.org", port: 80, transport: "udp" }); * port: 80,
* transport: "udp"
* });
* const listener2 = Deno.listenDatagram({
* hostname: "golang.org",
* port: 80,
* transport: "udp"
* });
* *
* Requires `allow-net` permission. */ * Requires `allow-net` permission. */
export function listen( export function listenDatagram(
options: ListenOptions & { transport: "udp" } options: ListenOptions & { transport: "udp" }
): DatagramConn; ): DatagramConn;
/** **UNSTABLE**: new API, yet to be vetted.
/** **UNSTABLE**: new API
* *
* Listen announces on the local transport address. * Listen announces on the local transport address.
* *
* const listener = Deno.listen({ path: "/foo/bar.sock", transport: "unixpacket" }) * const listener = Deno.listenDatagram({
* address: "/foo/bar.sock",
* transport: "unixpacket"
* });
* *
* Requires `allow-read` and `allow-write` permission. */ * Requires `allow-read` and `allow-write` permission. */
export function listen( export function listenDatagram(
options: UnixListenOptions & { transport: "unixpacket" } options: UnixListenOptions & { transport: "unixpacket" }
): DatagramConn; ): DatagramConn;

View file

@ -146,18 +146,10 @@ export function listen(
export function listen( export function listen(
options: UnixListenOptions & { transport: "unix" } options: UnixListenOptions & { transport: "unix" }
): Listener; ): Listener;
export function listen( export function listen(options: ListenOptions | UnixListenOptions): Listener {
options: ListenOptions & { transport: "udp" }
): DatagramConn;
export function listen(
options: UnixListenOptions & { transport: "unixpacket" }
): DatagramConn;
export function listen(
options: ListenOptions | UnixListenOptions
): Listener | DatagramConn {
let res; let res;
if (options.transport === "unix" || options.transport === "unixpacket") { if (options.transport === "unix") {
res = netOps.listen(options); res = netOps.listen(options);
} else { } else {
res = netOps.listen({ res = netOps.listen({
@ -167,15 +159,30 @@ export function listen(
}); });
} }
if ( return new ListenerImpl(res.rid, res.localAddr);
!options.transport || }
options.transport === "tcp" ||
options.transport === "unix" export function listenDatagram(
) { options: ListenOptions & { transport: "udp" }
return new ListenerImpl(res.rid, res.localAddr); ): DatagramConn;
export function listenDatagram(
options: UnixListenOptions & { transport: "unixpacket" }
): DatagramConn;
export function listenDatagram(
options: ListenOptions | UnixListenOptions
): DatagramConn {
let res;
if (options.transport === "unixpacket") {
res = netOps.listen(options);
} else { } else {
return new DatagramImpl(res.rid, res.localAddr); res = netOps.listen({
transport: "udp",
hostname: "127.0.0.1",
...(options as ListenOptions),
});
} }
return new DatagramImpl(res.rid, res.localAddr);
} }
export interface ConnectOptions { export interface ConnectOptions {

View file

@ -21,7 +21,7 @@ unitTest(
ignore: Deno.build.os === "windows", ignore: Deno.build.os === "windows",
}, },
function netUdpListenClose(): void { function netUdpListenClose(): void {
const socket = Deno.listen({ const socket = Deno.listenDatagram({
hostname: "127.0.0.1", hostname: "127.0.0.1",
port: 4500, port: 4500,
transport: "udp", transport: "udp",
@ -51,7 +51,7 @@ unitTest(
{ ignore: Deno.build.os === "windows", perms: { read: true, write: true } }, { ignore: Deno.build.os === "windows", perms: { read: true, write: true } },
function netUnixPacketListenClose(): void { function netUnixPacketListenClose(): void {
const filePath = Deno.makeTempFileSync(); const filePath = Deno.makeTempFileSync();
const socket = Deno.listen({ const socket = Deno.listenDatagram({
path: filePath, path: filePath,
transport: "unixpacket", transport: "unixpacket",
}); });
@ -227,12 +227,12 @@ unitTest(
unitTest( unitTest(
{ ignore: Deno.build.os === "windows", perms: { net: true } }, { ignore: Deno.build.os === "windows", perms: { net: true } },
async function netUdpSendReceive(): Promise<void> { async function netUdpSendReceive(): Promise<void> {
const alice = Deno.listen({ port: 4500, transport: "udp" }); const alice = Deno.listenDatagram({ port: 4500, transport: "udp" });
assert(alice.addr.transport === "udp"); assert(alice.addr.transport === "udp");
assertEquals(alice.addr.port, 4500); assertEquals(alice.addr.port, 4500);
assertEquals(alice.addr.hostname, "127.0.0.1"); assertEquals(alice.addr.hostname, "127.0.0.1");
const bob = Deno.listen({ port: 4501, transport: "udp" }); const bob = Deno.listenDatagram({ port: 4501, transport: "udp" });
assert(bob.addr.transport === "udp"); assert(bob.addr.transport === "udp");
assertEquals(bob.addr.port, 4501); assertEquals(bob.addr.port, 4501);
assertEquals(bob.addr.hostname, "127.0.0.1"); assertEquals(bob.addr.hostname, "127.0.0.1");
@ -256,11 +256,17 @@ unitTest(
{ ignore: Deno.build.os === "windows", perms: { read: true, write: true } }, { ignore: Deno.build.os === "windows", perms: { read: true, write: true } },
async function netUnixPacketSendReceive(): Promise<void> { async function netUnixPacketSendReceive(): Promise<void> {
const filePath = await Deno.makeTempFile(); const filePath = await Deno.makeTempFile();
const alice = Deno.listen({ path: filePath, transport: "unixpacket" }); const alice = Deno.listenDatagram({
path: filePath,
transport: "unixpacket",
});
assert(alice.addr.transport === "unixpacket"); assert(alice.addr.transport === "unixpacket");
assertEquals(alice.addr.path, filePath); assertEquals(alice.addr.path, filePath);
const bob = Deno.listen({ path: filePath, transport: "unixpacket" }); const bob = Deno.listenDatagram({
path: filePath,
transport: "unixpacket",
});
assert(bob.addr.transport === "unixpacket"); assert(bob.addr.transport === "unixpacket");
assertEquals(bob.addr.path, filePath); assertEquals(bob.addr.path, filePath);
@ -295,7 +301,7 @@ unitTest(
unitTest( unitTest(
{ ignore: Deno.build.os === "windows", perms: { net: true } }, { ignore: Deno.build.os === "windows", perms: { net: true } },
async function netUdpListenCloseWhileIterating(): Promise<void> { async function netUdpListenCloseWhileIterating(): Promise<void> {
const socket = Deno.listen({ port: 8000, transport: "udp" }); const socket = Deno.listenDatagram({ port: 8000, transport: "udp" });
const nextWhileClosing = socket[Symbol.asyncIterator]().next(); const nextWhileClosing = socket[Symbol.asyncIterator]().next();
socket.close(); socket.close();
assertEquals(await nextWhileClosing, { value: undefined, done: true }); assertEquals(await nextWhileClosing, { value: undefined, done: true });
@ -323,7 +329,10 @@ unitTest(
{ ignore: Deno.build.os === "windows", perms: { read: true, write: true } }, { ignore: Deno.build.os === "windows", perms: { read: true, write: true } },
async function netUnixPacketListenCloseWhileIterating(): Promise<void> { async function netUnixPacketListenCloseWhileIterating(): Promise<void> {
const filePath = Deno.makeTempFileSync(); const filePath = Deno.makeTempFileSync();
const socket = Deno.listen({ path: filePath, transport: "unixpacket" }); const socket = Deno.listenDatagram({
path: filePath,
transport: "unixpacket",
});
const nextWhileClosing = socket[Symbol.asyncIterator]().next(); const nextWhileClosing = socket[Symbol.asyncIterator]().next();
socket.close(); socket.close();
assertEquals(await nextWhileClosing, { value: undefined, done: true }); assertEquals(await nextWhileClosing, { value: undefined, done: true });

View file

@ -494,6 +494,9 @@ fn op_listen(
transport, transport,
transport_args: ArgsEnum::Ip(args), transport_args: ArgsEnum::Ip(args),
} => { } => {
if transport == "udp" {
state.check_unstable("Deno.listenDatagram");
}
state.check_net(&args.hostname, args.port)?; state.check_net(&args.hostname, args.port)?;
let addr = resolve_addr(&args.hostname, args.port)?; let addr = resolve_addr(&args.hostname, args.port)?;
let (rid, local_addr) = if transport == "tcp" { let (rid, local_addr) = if transport == "tcp" {
@ -521,6 +524,9 @@ fn op_listen(
transport, transport,
transport_args: ArgsEnum::Unix(args), transport_args: ArgsEnum::Unix(args),
} if transport == "unix" || transport == "unixpacket" => { } if transport == "unix" || transport == "unixpacket" => {
if transport == "unixpacket" {
state.check_unstable("Deno.listenDatagram");
}
let address_path = net_unix::Path::new(&args.path); let address_path = net_unix::Path::new(&args.path);
state.check_read(&address_path)?; state.check_read(&address_path)?;
state.check_write(&address_path)?; state.check_write(&address_path)?;