-
Notifications
You must be signed in to change notification settings - Fork 5.4k
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
fix(tls): flush send buffer in the background after closing TLS stream #10146
Conversation
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
|
||
impl Resource for TlsClientStreamResource { | ||
impl Resource for TlsStreamResource { | ||
fn name(&self) -> Cow<str> { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
A bit of a tangent but for my edification: why Cow<str>
instead of &'static str
? Literally all implementers call into()
on a &'static str
.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Good point actually. But I think changing that belongs in a separate commit.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can tokio-rustls be removed from cli/Cargo.toml and test_util/Cargo.toml now?
Hi, can you describe the problem? I am very interested in it. |
runtime/ops/tls.rs
Outdated
ready!(self.poll_io(cx, Flow::Write))?; | ||
|
||
match self.tls.write(buf) { | ||
Ok(0) => unreachable!(), |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It may return 0 when the internal buffer of rustls is full.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
That shouldn't happen, because poll_io()
returns Poll::Pending
when the buffer is full.
However it will return 0 when buf
is empty, so I removed the assertion anyway.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
No, it will not return to pending. see https://github.com/ctz/rustls/blob/47d309233f2d21ccf058d35c58d684e5e4c9c643/rustls/src/server/mod.rs#L738
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
No, it will not return to pending. see https://github.com/ctz/rustls/blob/47d309233f2d21ccf058d35c58d684e5e4c9c643/rustls/src/server/mod.rs#L738
poll_io()
returns Poll::Pending
when the buffer is full:
Line 325 in 800ae5e
true => Poll::Pending, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Sorry, I didn't see to poll_io
, you are right.
runtime/ops/tls.rs
Outdated
unsafe { &mut *(buf.unfilled_mut() as *mut [MaybeUninit<u8>] as *mut _) }; | ||
|
||
match self.tls.read(buf_slice) { | ||
Ok(0) => unreachable!(), |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think it will return 0 at eof.
runtime/ops/tls.rs
Outdated
) -> Poll<io::Result<()>> { | ||
ready!(self.poll_io(cx, Flow::Read))?; | ||
|
||
if matches!(self.rd_shut, Shut::TlsShut | Shut::TcpShut) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think it obscures the shutdown status of tcp stream and tls stream. When eof occurs in the tcp stream, there may still be readable data in the buffer of the tls stream.
op_crates/websocket/lib.rs
Outdated
@@ -161,7 +161,7 @@ where | |||
|
|||
let tls_connector = TlsConnector::from(Arc::new(config)); | |||
let dnsname = | |||
DNSNameRef::try_from_ascii_str(&domain).expect("Invalid DNS lookup"); | |||
DNSNameRef::try_from_ascii_str(&domain).expect("invalid hostname"); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
is this related to tokio-rustls?
cli/tests/unit/tls_test.ts
Outdated
@@ -32,7 +32,7 @@ unitTest( | |||
|
|||
await assertThrowsAsync(async () => { | |||
await Deno.connectTls({ hostname: "127.0.0.1", port: 3567 }); | |||
}, Error); | |||
}, TypeError); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
related?
cli/tests/listen_tls_alpn.ts
Outdated
@@ -8,5 +10,8 @@ const listener = Deno.listenTls({ | |||
console.log("READY"); | |||
|
|||
for await (const conn of listener) { | |||
if (await conn.read(new Uint8Array(1)) !== null) { | |||
throw new Error("should not receive data on TLS connection"); | |||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is this demonstrating the bug this PR is fixing?
From CLI, yes. But Note that |
@piscisaureus What's the status of this PR? |
denoland#10146) In denoland#9118, TLS streams were split into a "read half" and a "write half" using tokio::io::split() to allow concurrent Conn#read() and Conn#write() calls without one blocking the other. However, this introduced a bug: outgoing data gets discarded when the TLS stream is gracefully closed, because the read half is closed too early, before all TLS control data has been received. Fixes: denoland#9692 Fixes: denoland#10049 Fixes: denoland#10296 Fixes: denoland/std#750
denoland#10146) In denoland#9118, TLS streams were split into a "read half" and a "write half" using tokio::io::split() to allow concurrent Conn#read() and Conn#write() calls without one blocking the other. However, this introduced a bug: outgoing data gets discarded when the TLS stream is gracefully closed, because the read half is closed too early, before all TLS control data has been received. Fixes: denoland#9692 Fixes: denoland#10049 Fixes: denoland#10296 Fixes: denoland/std#750
…LS stream (denoland#10146)" This reverts commit 640d431.
In #9118, TLS streams were split into a "read half" and a "write half"
using
tokio::io::split()
to allow concurrentConn#read()
andConn#write()
calls without one blocking the other. However, thisintroduced a bug: outgoing data gets discarded when the TLS stream is
gracefully closed, because the read half is closed too early, before all
TLS control data has been received.
Fixes: #9692
Fixes: #10049
Fixes: #10296
Fixes: denoland/std#750