Skip to content
This repository has been archived by the owner on Aug 11, 2020. It is now read-only.

Commit

Permalink
quic: simplify alpn selection callback
Browse files Browse the repository at this point in the history
  • Loading branch information
jasnell committed Oct 10, 2019
1 parent 6b97000 commit f1d1c6d
Show file tree
Hide file tree
Showing 4 changed files with 36 additions and 26 deletions.
42 changes: 17 additions & 25 deletions src/node_quic_crypto.cc
Original file line number Diff line number Diff line change
Expand Up @@ -823,39 +823,31 @@ int Client_Hello_CB(
}
}

int ALPN_Select_Proto_CB(
int AlpnSelection(
SSL* ssl,
const unsigned char** out,
unsigned char* outlen,
const unsigned char* in,
unsigned int inlen,
void* arg) {
QuicSession* session = static_cast<QuicSession*>(SSL_get_app_data(ssl));
const uint8_t* alpn;
size_t alpnlen;
uint32_t version = session->GetNegotiatedVersion();

switch (version) {
case NGTCP2_PROTO_VER:
alpn = reinterpret_cast<const uint8_t*>(session->GetALPN().c_str());
alpnlen = session->GetALPN().length();
break;
default:
// Unexpected QUIC protocol version
return SSL_TLSEXT_ERR_NOACK;
}

for (auto p = in, end = in + inlen; p + alpnlen < end; p += *p + 1) {
if (std::equal(alpn, alpn + alpnlen, p)) {
*out = p + 1;
*outlen = *p;
return SSL_TLSEXT_ERR_OK;
}
unsigned char* tmp;

// The QuicServerSession supports exactly one ALPN identifier. If that does
// not match any of the ALPN identifiers provided in the client request,
// then we fail here. Note that this will not fail the TLS handshake, so
// we have to check later if the ALPN matches the expected identifier or not.
if (SSL_select_next_proto(
&tmp,
outlen,
reinterpret_cast<const unsigned char*>(session->GetALPN().c_str()),
session->GetALPN().length(),
in,
inlen) == OPENSSL_NPN_NO_OVERLAP) {
return SSL_TLSEXT_ERR_NOACK;
}

*out = alpn + 1;
*outlen = alpn[0];

*out = tmp;
return SSL_TLSEXT_ERR_OK;
}

Expand Down Expand Up @@ -1016,7 +1008,7 @@ void InitializeSecureContext(
SSL_CTX_set_options(**sc, ssl_server_opts);
SSL_CTX_set_mode(**sc, SSL_MODE_RELEASE_BUFFERS);
SSL_CTX_set_max_early_data(**sc, std::numeric_limits<uint32_t>::max());
SSL_CTX_set_alpn_select_cb(**sc, ALPN_Select_Proto_CB, nullptr);
SSL_CTX_set_alpn_select_cb(**sc, AlpnSelection, nullptr);
SSL_CTX_set_client_hello_cb(**sc, Client_Hello_CB, nullptr);
break;
case NGTCP2_CRYPTO_SIDE_CLIENT:
Expand Down
17 changes: 17 additions & 0 deletions src/node_quic_session.cc
Original file line number Diff line number Diff line change
Expand Up @@ -592,6 +592,12 @@ void QuicSession::HandleError() {
// need to do at this point is let the javascript side know.
void QuicSession::HandshakeCompleted() {
Debug(this, "Handshake is completed");

// TODO(@jasnell): We should determine if the ALPN
// protocol identifier was selected by this point.
// If no protocol identifier was selected, then we
// should stop here with an error.

session_stats_.handshake_completed_at = uv_hrtime();

HandleScope scope(env()->isolate());
Expand Down Expand Up @@ -1673,6 +1679,7 @@ void QuicSession::MemoryInfo(MemoryTracker* tracker) const {
// QuicServerSession
QuicServerSession::InitialPacketResult QuicServerSession::Accept(
ngtcp2_pkt_hd* hd,
uint32_t version,
const uint8_t* data,
ssize_t nread) {
// The initial packet is too short and not a valid QUIC packet.
Expand All @@ -1685,6 +1692,16 @@ QuicServerSession::InitialPacketResult QuicServerSession::Accept(
case 1:
return PACKET_VERSION;
}

// Currently, we only understand one version of the QUIC
// protocol, but that could change in the future. If it
// does change, the following check needs to be updated
// to check against a range of possible versions.
// See NGTCP2_PROTO_VER and NGTCP2_PROTO_VER_MAX in the
// ngtcp2.h header file for more details.
if (version != NGTCP2_PROTO_VER)
return PACKET_VERSION;

return PACKET_OK;
}

Expand Down
1 change: 1 addition & 0 deletions src/node_quic_session.h
Original file line number Diff line number Diff line change
Expand Up @@ -1000,6 +1000,7 @@ class QuicServerSession : public QuicSession {

static InitialPacketResult Accept(
ngtcp2_pkt_hd* hd,
uint32_t version,
const uint8_t* data,
ssize_t nread);

Expand Down
2 changes: 1 addition & 1 deletion src/node_quic_socket.cc
Original file line number Diff line number Diff line change
Expand Up @@ -655,7 +655,7 @@ BaseObjectPtr<QuicSession> QuicSocket::AcceptInitialPacket(

// Perform some initial checks on the packet to see if it is an
// acceptable initial packet with the right QUIC version.
switch (QuicServerSession::Accept(&hd, data, nread)) {
switch (QuicServerSession::Accept(&hd, version, data, nread)) {
case QuicServerSession::InitialPacketResult::PACKET_VERSION:
SendVersionNegotiation(version, dcid, scid, addr);
// Fall through
Expand Down

0 comments on commit f1d1c6d

Please sign in to comment.