Add alpn() & ciphersuite() methods with a default implementation to QuicCryptoStream.

Note:
The new methods are expected to replace equivalent methods in Envoy (envoy/src/source/common/tls/connection_info_impl_base.h).
PiperOrigin-RevId: 917214206
diff --git a/quiche/quic/core/quic_crypto_stream.cc b/quiche/quic/core/quic_crypto_stream.cc
index 721da56..e8f54bb 100644
--- a/quiche/quic/core/quic_crypto_stream.cc
+++ b/quiche/quic/core/quic_crypto_stream.cc
@@ -10,6 +10,7 @@
 #include <string>
 #include <vector>
 
+#include "absl/base/nullability.h"
 #include "absl/strings/str_cat.h"
 #include "absl/strings/string_view.h"
 #include "openssl/base.h"
@@ -29,6 +30,7 @@
 #include "quiche/quic/platform/api/quic_logging.h"
 #include "quiche/common/platform/api/quiche_bug_tracker.h"
 #include "quiche/common/platform/api/quiche_flag_utils.h"
+#include "quiche/common/platform/api/quiche_logging.h"
 #include "quiche/common/quiche_buffer_allocator.h"
 
 namespace quic {
@@ -630,5 +632,29 @@
   return {};
 }
 
+const SSL_CIPHER* absl_nullable QuicCryptoStream::ciphersuite() const {
+  QUICHE_DCHECK(VersionIsIetfQuic(session()->transport_version()));
+  SSL* ssl = GetSsl();
+  if (ssl == nullptr) {
+    return nullptr;
+  }
+  return SSL_get_current_cipher(ssl);
+}
+
+absl::string_view QuicCryptoStream::alpn() const {
+  QUICHE_DCHECK(VersionIsIetfQuic(session()->transport_version()));
+  SSL* ssl = GetSsl();
+  if (ssl == nullptr) {
+    return {};
+  }
+  const unsigned char* data = nullptr;
+  unsigned int data_len = 0;
+  SSL_get0_alpn_selected(ssl, &data, &data_len);
+  if (data == nullptr) {
+    return {};
+  }
+  return absl::string_view(reinterpret_cast<const char*>(data), data_len);
+}
+
 #undef ENDPOINT  // undef for jumbo builds
 }  // namespace quic
diff --git a/quiche/quic/core/quic_crypto_stream.h b/quiche/quic/core/quic_crypto_stream.h
index b76be3f..ab93451 100644
--- a/quiche/quic/core/quic_crypto_stream.h
+++ b/quiche/quic/core/quic_crypto_stream.h
@@ -11,6 +11,7 @@
 #include <string>
 #include <vector>
 
+#include "absl/base/nullability.h"
 #include "absl/strings/string_view.h"
 #include "openssl/ssl.h"
 #include "quiche/quic/core/crypto/crypto_framer.h"
@@ -179,6 +180,12 @@
 
   virtual absl::string_view sni() const;
 
+  // These methods should only be called with IETF QUIC.
+  // Returns the cipher suite in use.
+  virtual const SSL_CIPHER* absl_nullable ciphersuite() const;
+  // Returns the ALPN in use.
+  virtual absl::string_view alpn() const;
+
   // Called to cancel retransmission of unencrypted crypto stream data.
   void NeuterUnencryptedStreamData();
 
diff --git a/quiche/quic/core/tls_client_handshaker_test.cc b/quiche/quic/core/tls_client_handshaker_test.cc
index a5df77e..6ca11a1 100644
--- a/quiche/quic/core/tls_client_handshaker_test.cc
+++ b/quiche/quic/core/tls_client_handshaker_test.cc
@@ -318,6 +318,9 @@
   EXPECT_FALSE(stream()->MatchedTrustAnchorIdForTesting());
   EXPECT_TRUE(stream()->one_rtt_keys_available());
   EXPECT_FALSE(stream()->IsResumption());
+  EXPECT_EQ(stream()->sni(), kServerHostname);
+  EXPECT_EQ(stream()->alpn(), AlpnForVersion(stream()->version()));
+  EXPECT_NE(stream()->ciphersuite(), nullptr);
 }
 
 TEST_P(TlsClientHandshakerTest, ConnectionClosedOnTlsError) {
diff --git a/quiche/quic/core/tls_server_handshaker_test.cc b/quiche/quic/core/tls_server_handshaker_test.cc
index a5d9b63..9f41676 100644
--- a/quiche/quic/core/tls_server_handshaker_test.cc
+++ b/quiche/quic/core/tls_server_handshaker_test.cc
@@ -551,6 +551,11 @@
   CompleteCryptoHandshake();
   EXPECT_TRUE(server_stream()->version().IsIetfQuic());
   ExpectHandshakeSuccessful();
+
+  EXPECT_EQ(server_stream()->sni(), kServerHostname);
+  EXPECT_EQ(server_stream()->alpn(),
+            AlpnForVersion(server_stream()->version()));
+  EXPECT_NE(server_stream()->ciphersuite(), nullptr);
 }
 
 TEST_P(TlsServerHandshakerTest, HandshakeWithAsyncSelectCertSuccess) {