Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(ext/net): Add Conn.setNoDelay and Conn.setKeepAlive #13103

Merged
merged 16 commits into from
Jan 31, 2022
Merged
36 changes: 36 additions & 0 deletions cli/tests/unit/net_test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -238,6 +238,42 @@ Deno.test({ permissions: { net: true } }, async function netTcpDialListen() {
conn.close();
});

Deno.test({ permissions: { net: true } }, async function netTcpSetNoDelay() {
const listener = Deno.listen({ port: 3500 });
listener.accept().then(
async (conn) => {
assert(conn.remoteAddr != null);
assert(conn.localAddr.transport === "tcp");
assertEquals(conn.localAddr.hostname, "127.0.0.1");
assertEquals(conn.localAddr.port, 3500);
await conn.write(new Uint8Array([1, 2, 3]));
conn.close();
},
);

const conn = await Deno.connect({ hostname: "127.0.0.1", port: 3500 });
conn.setNoDelay(true);
assert(conn.remoteAddr.transport === "tcp");
assertEquals(conn.remoteAddr.hostname, "127.0.0.1");
assertEquals(conn.remoteAddr.port, 3500);
assert(conn.localAddr != null);
const buf = new Uint8Array(1024);
const readResult = await conn.read(buf);
assertEquals(3, readResult);
assertEquals(1, buf[0]);
assertEquals(2, buf[1]);
assertEquals(3, buf[2]);
assert(conn.rid > 0);

assert(readResult !== null);
Copy link

@lucasfcosta lucasfcosta Dec 27, 2021

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Considering that:

  1. L262 already checks whether readResult equals 3
  2. readResult is a const and assigned a primitive

Do we need this assertion or is it redundant?


const readResult2 = await conn.read(buf);
assertEquals(readResult2, null);

listener.close();
conn.close();
});

Deno.test(
{
ignore: Deno.build.os === "windows",
Expand Down
4 changes: 4 additions & 0 deletions ext/net/01_net.js
Original file line number Diff line number Diff line change
Expand Up @@ -95,6 +95,10 @@
closeWrite() {
return shutdown(this.rid);
}

setNoDelay(nodelay = true) {
return core.opSync("op_set_nodelay", this.rid, nodelay);
}
}

class Listener {
Expand Down
12 changes: 12 additions & 0 deletions ext/net/io.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
// Copyright 2018-2021 the Deno authors. All rights reserved. MIT license.

use deno_core::error::generic_error;
use deno_core::error::AnyError;
use deno_core::AsyncMutFuture;
use deno_core::AsyncRefCell;
Expand Down Expand Up @@ -118,6 +119,17 @@ impl Resource for TcpStreamResource {
}
}

impl TcpStreamResource {
pub fn set_nodelay(self: Rc<Self>, nodelay: bool) -> Result<(), AnyError> {
if let Some(wr) = RcRef::map(self, |r| &r.wr).try_borrow() {
let stream = wr.as_ref().as_ref();
return Ok(stream.set_nodelay(nodelay)?);
}

Err(generic_error("Unable to set no delay"))
}
}

#[cfg(unix)]
pub type UnixStreamResource =
FullDuplexResource<unix::OwnedReadHalf, unix::OwnedWriteHalf>;
Expand Down
2 changes: 2 additions & 0 deletions ext/net/lib.deno_net.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,8 @@ declare namespace Deno {
/** Shuts down (`shutdown(2)`) the write side of the connection. Most
* callers should just use `close()`. */
closeWrite(): Promise<void>;
/** Enable/disable the use of Nagle's algorithm. Defaults to true */
setNoDelay(nodelay?: boolean): void;
}

// deno-lint-ignore no-empty-interface
Expand Down
11 changes: 11 additions & 0 deletions ext/net/ops.rs
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,7 @@ pub fn init<P: NetPermissions + 'static>() -> Vec<OpPair> {
("op_dgram_recv", op_async(op_dgram_recv)),
("op_dgram_send", op_async(op_dgram_send::<P>)),
("op_dns_resolve", op_async(op_dns_resolve::<P>)),
("op_set_nodelay", op_sync(op_set_nodelay::<P>)),
]
}

Expand Down Expand Up @@ -665,6 +666,16 @@ where
Ok(results)
}

pub fn op_set_nodelay<NP>(
state: &mut OpState,
rid: ResourceId,
nodelay: bool,
) -> Result<(), AnyError> {
let resource: Rc<TcpStreamResource> =
state.resource_table.get::<TcpStreamResource>(rid)?;
resource.set_nodelay(nodelay)
}

fn rdata_to_return_record(
ty: RecordType,
) -> impl Fn(&RData) -> Option<DnsReturnRecord> {
Expand Down