Implement QUIC ALPN selection on the server side.
This also fixes the bugs in client side found by a full custom ALPN test, and removes a tautological check from server-side ALPN parser.
gfe-relnote: n/a (protected by disabled quic_tls flag)
PiperOrigin-RevId: 266319592
Change-Id: I9e06b383abe187286f31d3cbce8be99e9370c9f2
diff --git a/quic/core/tls_server_handshaker.cc b/quic/core/tls_server_handshaker.cc
index a2ea397..0b4215d 100644
--- a/quic/core/tls_server_handshaker.cc
+++ b/quic/core/tls_server_handshaker.cc
@@ -352,41 +352,38 @@
return SSL_TLSEXT_ERR_NOACK;
}
- std::string expected_alpn_string =
- AlpnForVersion(session()->connection()->version());
-
CBS all_alpns;
CBS_init(&all_alpns, in, in_len);
+ std::vector<QuicStringPiece> alpns;
while (CBS_len(&all_alpns) > 0) {
CBS alpn;
if (!CBS_get_u8_length_prefixed(&all_alpns, &alpn)) {
QUIC_DLOG(ERROR) << "Failed to parse ALPN length";
return SSL_TLSEXT_ERR_NOACK;
}
+
const size_t alpn_length = CBS_len(&alpn);
- if (alpn_length >
- static_cast<size_t>(std::numeric_limits<uint8_t>::max())) {
- QUIC_BUG << "Parsed impossible ALPN length " << alpn_length;
- return SSL_TLSEXT_ERR_NOACK;
- }
if (alpn_length == 0) {
QUIC_DLOG(ERROR) << "Received invalid zero-length ALPN";
return SSL_TLSEXT_ERR_NOACK;
}
- std::string alpn_string(reinterpret_cast<const char*>(CBS_data(&alpn)),
- alpn_length);
- if (alpn_string == expected_alpn_string) {
- QUIC_DLOG(INFO) << "Server selecting ALPN '" << alpn_string << "'";
- *out_len = static_cast<uint8_t>(alpn_length);
- *out = CBS_data(&alpn);
- valid_alpn_received_ = true;
- return SSL_TLSEXT_ERR_OK;
- }
+
+ alpns.emplace_back(reinterpret_cast<const char*>(CBS_data(&alpn)),
+ alpn_length);
}
- QUIC_DLOG(ERROR) << "No known ALPN provided by client";
- return SSL_TLSEXT_ERR_NOACK;
+ auto selected_alpn = session()->SelectAlpn(alpns);
+ if (selected_alpn == alpns.end()) {
+ QUIC_DLOG(ERROR) << "No known ALPN provided by client";
+ return SSL_TLSEXT_ERR_NOACK;
+ }
+
+ session()->OnAlpnSelected(*selected_alpn);
+ valid_alpn_received_ = true;
+ *out_len = selected_alpn->size();
+ *out = reinterpret_cast<const uint8_t*>(selected_alpn->data());
+ return SSL_TLSEXT_ERR_OK;
}
} // namespace quic