-
Notifications
You must be signed in to change notification settings - Fork 5.2k
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: ALPN support in Deno.connectTls()
#12786
Conversation
7345c69
to
9875b60
Compare
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.
Thanks for the work on this @1st1! I have added some comments about the API surface.
We'll also need some tests for this feature (in cli/tests/unit/tls_test.ts
). For test cases you could create a server with Deno.listenTls
with some ALPN protocols and then connect to it during the test and check that the negotiation works correctly. There are some examples on how to do that in that file.
Also, this option should be added to Deno.startTls
in addition to Deno.connectTls
.
@lucacasonato Thanks for the review! I've updated the PR implementing all of your suggestions. Please take another look. |
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.
Test looks great, thanks.
Deno.connectTls()
.Deno.connectTls()
I think the CI timeouts aren't related to this PR. @lucacasonato let me know if there's anything else left to do. |
Actually they are. Investigating. |
I'm not sure that is the right fix. The same hang could happen, it just isn't triggered by our tests? |
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.
Maybe turn handshake_done
into a Cell<Option<TlsHandshakeInfo>>
and store the handshake info in there right after handshaking?
Just looked into it, that seems to be the right way to go about it indeed. |
My thinking was that
This is what I also settled on, although it seems that I can't wrap
So I'm using |
|
Yes, I've made Compile error:
|
Ok let me look into it. |
I can get around not using See the diffdiff --git a/ext/net/ops_tls.rs b/ext/net/ops_tls.rs
index 2edbfc08c..d98247c9d 100644
--- a/ext/net/ops_tls.rs
+++ b/ext/net/ops_tls.rs
@@ -56,6 +56,7 @@ use io::Read;
use io::Write;
use serde::Deserialize;
use std::borrow::Cow;
+use std::cell::Cell;
use std::cell::RefCell;
use std::convert::From;
use std::fs::File;
@@ -716,7 +717,7 @@ pub fn init<P: NetPermissions + 'static>() -> Vec<OpPair> {
pub struct TlsStreamResource {
rd: AsyncRefCell<ReadHalf>,
wr: AsyncRefCell<WriteHalf>,
- handshake_done: RefCell<Option<TlsHandshakeInfo>>,
+ handshake_done: Cell<Option<TlsHandshakeInfo>>,
cancel_handle: CancelHandle, // Only read and handshake ops get canceled.
}
@@ -725,7 +726,7 @@ impl TlsStreamResource {
Self {
rd: rd.into(),
wr: wr.into(),
- handshake_done: RefCell::new(None),
+ handshake_done: Cell::new(None),
cancel_handle: Default::default(),
}
}
@@ -765,8 +766,10 @@ impl TlsStreamResource {
pub async fn handshake(
self: &Rc<Self>,
) -> Result<TlsHandshakeInfo, AnyError> {
- if let Some(tls_info) = &*self.handshake_done.borrow() {
- return Ok(tls_info.clone());
+ let hs_result = self.handshake_done.replace(None);
+ if let Some(tls_info) = hs_result {
+ self.handshake_done.set(Some(tls_info.clone()));
+ return Ok(tls_info);
}
let mut wr = RcRef::map(self, |r| &r.wr).borrow_mut().await;
@@ -775,7 +778,7 @@ impl TlsStreamResource {
let alpn_protocol = wr.get_alpn_protocol();
let tls_info = TlsHandshakeInfo { alpn_protocol };
- self.handshake_done.replace(Some(tls_info.clone()));
+ self.handshake_done.set(Some(tls_info.clone()));
Ok(tls_info)
}
} but the compiler is still not happy with declaring Error:
|
Sure, really appreciate this! Is there an issue with swapping |
Not really, I was just being pedantic. |
Final nit, maybe we can rename Other than that, this looks good to go. |
Sure, done. |
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.
LGTM @1st1. Excellent work on your first contribution! 🎉
I can't land the PR right away, because the 1.17 feature merge window has not opened yet. It will open after the 1.16.3 release next Tuesday (23 November 2021).
Thanks @lucacasonato. Feel free to ping me if you need help with rebasing when the merge window is open. |
A friendly ping: let's merge this? Just want to make sure we get this into the next release. |
@1st1 Could you rebase the PR and apply the following patch: From b933c778addf96d816f003a58816ec2cc1fcae5e Mon Sep 17 00:00:00 2001
From: Luca Casonato <hello@lcas.dev>
Date: Fri, 26 Nov 2021 10:14:13 +0100
Subject: [PATCH] update tests
---
cli/tests/unit/tls_test.ts | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/cli/tests/unit/tls_test.ts b/cli/tests/unit/tls_test.ts
index f47c6ac90..7e6d68900 100644
--- a/cli/tests/unit/tls_test.ts
+++ b/cli/tests/unit/tls_test.ts
@@ -364,7 +364,7 @@ Deno.test(
},
);
-unitTest(
+Deno.test(
{ permissions: { read: true, net: true } },
async function tlsServerAlpnListenStartTls() {
const [serverConn, clientConn] = await tlsAlpn(true);
@@ -380,7 +380,7 @@ unitTest(
},
);
-unitTest(
+Deno.test(
{ permissions: { read: true, net: true } },
async function tlsServerStreamHalfCloseSendOneByte() {
const [serverConn, clientConn] = await tlsPair();
--
2.34.0
I'd do it myself, but I don't have write access to your fork :-) |
* Make `connectTls()` accept `alpnProtocols` option (string[]), just like `listenTls()`. * Add `getAgreedAlpnProtocol(): Promise<string | null>` method to query the protocol agreed with the peer via ALPN. The `alpnProtocols` is added as an unstable API.
While there: * Fix the selected ALPN protocol from being stored as a UTF8-encoded `String` to `deno_core::ByteString`. * Add `alpnProtocols` option to `Deno.startTls()`. * Add tests.
Done!
Hm, I don't see a checkbox to grant you push privs... I'll look for it, but in the meantime if there's anything else you want to be fixed in the PR let me know. |
Make
connectTls()
acceptalpnProtocols
option(string[]), just like
listenTls()
.Add
alpnProtocol
toTlsConn#handshake
returnvalue to query the protocol agreed with the peer via ALPN.
The
alpnProtocols
is added as an unstable API (mirroringhow it's supported in
listenTls()
).We need this change for making a Deno client for EdgeDB. EdgeDB
requires TLS by default and uses ALPN to upgrade connections to
its binary protocol. Without these APIs we can't support Deno,
something we really want to have.
Fixes: #11479