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

src: optimize ALPN callback #44875

Closed
wants to merge 2 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
7 changes: 2 additions & 5 deletions lib/_tls_wrap.js
Expand Up @@ -786,11 +786,8 @@ TLSSocket.prototype._init = function(socket, wrap) {
ssl.enableCertCb();
}

if (options.ALPNProtocols) {
// Keep reference in secureContext not to be GC-ed
ssl._secureContext.alpnBuffer = options.ALPNProtocols;
ssl.setALPNProtocols(ssl._secureContext.alpnBuffer);
}
if (options.ALPNProtocols)
ssl.setALPNProtocols(options.ALPNProtocols);

if (options.pskCallback && ssl.enablePskCallback) {
validateFunction(options.pskCallback, 'pskCallback');
Expand Down
6 changes: 0 additions & 6 deletions src/crypto/crypto_common.cc
Expand Up @@ -89,12 +89,6 @@ void LogSecret(
keylog_cb(ssl.get(), line.c_str());
}

bool SetALPN(const SSLPointer& ssl, std::string_view alpn) {
return SSL_set_alpn_protos(ssl.get(),
reinterpret_cast<const uint8_t*>(alpn.data()),
alpn.length()) == 0;
}

MaybeLocal<Value> GetSSLOCSPResponse(
Environment* env,
SSL* ssl,
Expand Down
3 changes: 0 additions & 3 deletions src/crypto/crypto_common.h
Expand Up @@ -33,9 +33,6 @@ void LogSecret(
const unsigned char* secret,
size_t secretlen);

// TODO(tniessen): use std::u8string_view when we switch to C++20.
bool SetALPN(const SSLPointer& ssl, std::string_view alpn);

v8::MaybeLocal<v8::Value> GetSSLOCSPResponse(
Environment* env,
SSL* ssl,
Expand Down
44 changes: 15 additions & 29 deletions src/crypto/crypto_tls.cc
Expand Up @@ -225,26 +225,17 @@ int SelectALPNCallback(
const unsigned char* in,
unsigned int inlen,
void* arg) {
TLSWrap* w = static_cast<TLSWrap*>(SSL_get_app_data(s));
Environment* env = w->env();
HandleScope handle_scope(env->isolate());
Context::Scope context_scope(env->context());
TLSWrap* w = static_cast<TLSWrap*>(arg);
const std::vector<unsigned char>& alpn_protos = w->alpn_protos_;

Local<Value> alpn_buffer =
w->object()->GetPrivate(
env->context(),
env->alpn_buffer_private_symbol()).FromMaybe(Local<Value>());
if (UNLIKELY(alpn_buffer.IsEmpty()) || !alpn_buffer->IsArrayBufferView())
return SSL_TLSEXT_ERR_NOACK;
if (alpn_protos.empty()) return SSL_TLSEXT_ERR_NOACK;

ArrayBufferViewContents<unsigned char> alpn_protos(alpn_buffer);
int status = SSL_select_next_proto(
const_cast<unsigned char**>(out),
outlen,
alpn_protos.data(),
alpn_protos.length(),
in,
inlen);
int status = SSL_select_next_proto(const_cast<unsigned char**>(out),
outlen,
alpn_protos.data(),
alpn_protos.size(),
in,
inlen);

// Previous versions of Node.js returned SSL_TLSEXT_ERR_NOACK if no protocol
// match was found. This would neither cause a fatal alert nor would it result
Expand Down Expand Up @@ -1529,19 +1520,14 @@ void TLSWrap::SetALPNProtocols(const FunctionCallbackInfo<Value>& args) {
if (args.Length() < 1 || !Buffer::HasInstance(args[0]))
return env->ThrowTypeError("Must give a Buffer as first argument");

ArrayBufferViewContents<uint8_t> protos(args[0].As<ArrayBufferView>());
SSL* ssl = w->ssl_.get();
if (w->is_client()) {
ArrayBufferViewContents<char> protos(args[0].As<ArrayBufferView>());
CHECK(SetALPN(w->ssl_, {protos.data(), protos.length()}));
CHECK_EQ(0, SSL_set_alpn_protos(ssl, protos.data(), protos.length()));
} else {
CHECK(
w->object()->SetPrivate(
env->context(),
env->alpn_buffer_private_symbol(),
args[0]).FromJust());
// Server should select ALPN protocol from list of advertised by client
SSL_CTX_set_alpn_select_cb(SSL_get_SSL_CTX(w->ssl_.get()),
SelectALPNCallback,
nullptr);
w->alpn_protos_ = std::vector<unsigned char>(
protos.data(), protos.data() + protos.length());
SSL_CTX_set_alpn_select_cb(SSL_get_SSL_CTX(ssl), SelectALPNCallback, w);
}
}

Expand Down
4 changes: 4 additions & 0 deletions src/crypto/crypto_tls.h
Expand Up @@ -34,6 +34,7 @@
#include <openssl/ssl.h>

#include <string>
#include <vector>

namespace node {
namespace crypto {
Expand Down Expand Up @@ -283,6 +284,9 @@ class TLSWrap : public AsyncWrap,
void* cert_cb_arg_ = nullptr;

BIOPointer bio_trace_;

public:
std::vector<unsigned char> alpn_protos_; // Accessed by SelectALPNCallback.
};

} // namespace crypto
Expand Down
1 change: 0 additions & 1 deletion src/env_properties.h
Expand Up @@ -18,7 +18,6 @@
// for the sake of convenience. Strings should be ASCII-only and have a
// "node:" prefix to avoid name clashes with third-party code.
#define PER_ISOLATE_PRIVATE_SYMBOL_PROPERTIES(V) \
V(alpn_buffer_private_symbol, "node:alpnBuffer") \
V(arrow_message_private_symbol, "node:arrowMessage") \
V(contextify_context_private_symbol, "node:contextify:context") \
V(contextify_global_private_symbol, "node:contextify:global") \
Expand Down
1 change: 0 additions & 1 deletion typings/internalBinding/util.d.ts
Expand Up @@ -9,7 +9,6 @@ declare namespace InternalUtilBinding {

declare function InternalBinding(binding: 'util'): {
// PER_ISOLATE_PRIVATE_SYMBOL_PROPERTIES, defined in src/env.h
alpn_buffer_private_symbol: 0;
arrow_message_private_symbol: 1;
contextify_context_private_symbol: 2;
contextify_global_private_symbol: 3;
Expand Down