You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@trafficserver.apache.org by ma...@apache.org on 2017/08/23 07:02:33 UTC

[trafficserver] branch quic-latest updated: Add support for ALPN on QUIC

This is an automated email from the ASF dual-hosted git repository.

maskit pushed a commit to branch quic-latest
in repository https://gitbox.apache.org/repos/asf/trafficserver.git


The following commit(s) were added to refs/heads/quic-latest by this push:
     new 5a5d53f  Add support for ALPN on QUIC
5a5d53f is described below

commit 5a5d53f384fe5ed5526676678e2bd44d9b4e0610
Author: Masakazu Kitajo <ma...@apache.org>
AuthorDate: Wed Aug 23 16:00:40 2017 +0900

    Add support for ALPN on QUIC
    
    Since there's only one application layer protocol now, NextProtocolAccept is
    not introduced yet.
---
 iocore/net/P_QUICNetVConnection.h |  7 +++++++
 iocore/net/P_QUICPacketHandler.h  |  1 +
 iocore/net/QUICNetProcessor.cc    |  1 +
 iocore/net/QUICNetVConnection.cc  | 37 ++++++++++++++++++++++++++++++++-----
 iocore/net/quic/QUICCrypto.cc     |  6 ++++++
 iocore/net/quic/QUICCrypto.h      |  3 +++
 iocore/net/quic/QUICGlobals.cc    | 21 +++++++++++++++++++++
 iocore/net/quic/QUICGlobals.h     |  4 ++++
 iocore/net/quic/QUICHandshake.cc  |  7 +++----
 iocore/net/quic/QUICHandshake.h   |  2 +-
 lib/records/I_RecHttp.h           |  1 +
 lib/records/RecHttp.cc            | 19 ++++++++++++++++++-
 lib/ts/apidefs.h.in               |  3 +++
 lib/ts/ink_inet.cc                |  1 +
 lib/ts/ink_inet.h                 |  1 +
 proxy/http/HttpProxyServerMain.cc |  7 +++++--
 16 files changed, 108 insertions(+), 13 deletions(-)

diff --git a/iocore/net/P_QUICNetVConnection.h b/iocore/net/P_QUICNetVConnection.h
index 8e5586c..a2e6cf3 100644
--- a/iocore/net/P_QUICNetVConnection.h
+++ b/iocore/net/P_QUICNetVConnection.h
@@ -104,6 +104,8 @@ typedef std::unique_ptr<uint8_t> ats_uint8_t_unique_ptr;
 struct QUICPacketHandler;
 class QUICLossDetector;
 
+class SSLNextProtocolSet;
+
 /**
  * @class QUICNetVConnection
  * @brief A NetVConnection for a QUIC network socket
@@ -160,6 +162,9 @@ public:
   virtual void net_read_io(NetHandler *nh, EThread *lthread) override;
   virtual int64_t load_buffer_and_write(int64_t towrite, MIOBufferAccessor &buf, int64_t &total_written, int &needs) override;
 
+  SSLNextProtocolSet *next_protocol_set();
+  void registerNextProtocolSet(SSLNextProtocolSet *s);
+
   // QUICConnection
   uint32_t maximum_quic_packet_size() override;
   uint32_t minimum_quic_packet_size() override;
@@ -193,6 +198,8 @@ private:
 
   uint32_t _pmtu = 1280;
 
+  SSLNextProtocolSet *_next_protocol_set = nullptr;
+
   std::unique_ptr<QUICTransportParameters> _local_transport_parameters  = nullptr;
   std::unique_ptr<QUICTransportParameters> _remote_transport_parameters = nullptr;
 
diff --git a/iocore/net/P_QUICPacketHandler.h b/iocore/net/P_QUICPacketHandler.h
index 64463e4..ce77b4a 100644
--- a/iocore/net/P_QUICPacketHandler.h
+++ b/iocore/net/P_QUICPacketHandler.h
@@ -28,6 +28,7 @@
 #include "P_NetAccept.h"
 
 class QUICNetVConnection;
+class QUICPacket;
 
 struct QUICPacketHandler : public NetAccept {
 public:
diff --git a/iocore/net/QUICNetProcessor.cc b/iocore/net/QUICNetProcessor.cc
index f635210..291dfab 100644
--- a/iocore/net/QUICNetProcessor.cc
+++ b/iocore/net/QUICNetProcessor.cc
@@ -68,6 +68,7 @@ QUICNetProcessor::start(int, size_t stacksize)
   this->_ssl_ctx = SSL_CTX_new(TLS_method());
   SSL_CTX_set_min_proto_version(this->_ssl_ctx, TLS1_3_VERSION);
   SSL_CTX_set_max_proto_version(this->_ssl_ctx, TLS1_3_VERSION);
+  SSL_CTX_set_alpn_select_cb(this->_ssl_ctx, QUIC::ssl_select_next_protocol, nullptr);
   SSL_CTX_add_custom_ext(this->_ssl_ctx, QUICTransportParametersHandler::TRANSPORT_PARAMETER_ID,
                          SSL_EXT_TLS_ONLY | SSL_EXT_CLIENT_HELLO | SSL_EXT_TLS1_3_ENCRYPTED_EXTENSIONS,
                          &QUICTransportParametersHandler::add, &QUICTransportParametersHandler::free, nullptr,
diff --git a/iocore/net/QUICNetVConnection.cc b/iocore/net/QUICNetVConnection.cc
index e34f13c..1d44f42 100644
--- a/iocore/net/QUICNetVConnection.cc
+++ b/iocore/net/QUICNetVConnection.cc
@@ -33,6 +33,8 @@
 #include "BIO_fastopen.h"
 #include "Log.h"
 
+#include "P_SSLNextProtocolSet.h"
+
 #include "QUICEchoApp.h"
 #include "QUICDebugNames.h"
 #include "QUICEvents.h"
@@ -63,6 +65,11 @@ QUICNetVConnection::init(UDPConnection *udp_con, QUICPacketHandler *packet_handl
   this->_transmitter_mutex = new_ProxyMutex();
   this->_packet_handler    = packet_handler;
   this->_quic_connection_id.randomize();
+
+  // FIXME These should be done by HttpProxyServerMain
+  SSLNextProtocolSet *next_protocol_set = new SSLNextProtocolSet();
+  next_protocol_set->registerEndpoint(TS_ALPN_PROTOCOL_HTTP_QUIC, nullptr);
+  this->registerNextProtocolSet(next_protocol_set);
 }
 
 VIO *
@@ -509,6 +516,18 @@ QUICNetVConnection::load_buffer_and_write(int64_t towrite, MIOBufferAccessor &bu
   return 0;
 }
 
+void
+QUICNetVConnection::registerNextProtocolSet(SSLNextProtocolSet *s)
+{
+  this->_next_protocol_set = s;
+}
+
+SSLNextProtocolSet *
+QUICNetVConnection::next_protocol_set()
+{
+  return this->_next_protocol_set;
+}
+
 QUICError
 QUICNetVConnection::_state_handshake_process_initial_client_packet(std::unique_ptr<const QUICPacket> packet)
 {
@@ -719,12 +738,20 @@ QUICNetVConnection::_build_packet(ats_unique_buf buf, size_t len, bool retransmi
 QUICApplication *
 QUICNetVConnection::_create_application()
 {
-  const uint8_t *application = this->_handshake_handler->negotiated_application_name();
-  if (memcmp(application, "hq", 2) == 0) {
-    return new QUICEchoApp(this);
+  const uint8_t *app_name;
+  unsigned int app_name_len = 0;
+  this->_handshake_handler->negotiated_application_name(&app_name, &app_name_len);
+  if (app_name) {
+    DebugQUICCon("ALPN: %.*s", app_name_len, app_name);
+    if (memcmp(TS_ALPN_PROTOCOL_HTTP_QUIC, app_name, app_name_len) == 0) {
+      return new QUICEchoApp(this);
+    } else {
+      DebugQUICCon("Negotiated application is not available");
+      ink_assert(false);
+      return nullptr;
+    }
   } else {
-    DebugQUICCon("Unknown application has been negotiated: %s", application);
-    ink_assert(false);
+    DebugQUICCon("Failed to negotiate application");
     return nullptr;
   }
 }
diff --git a/iocore/net/quic/QUICCrypto.cc b/iocore/net/quic/QUICCrypto.cc
index 8eb1385..53b2799 100644
--- a/iocore/net/quic/QUICCrypto.cc
+++ b/iocore/net/quic/QUICCrypto.cc
@@ -242,6 +242,12 @@ QUICCrypto::update_server_keymaterial()
   // return 1;
 }
 
+SSL *
+QUICCrypto::ssl_handle()
+{
+  return this->_ssl;
+}
+
 bool
 QUICCrypto::encrypt(uint8_t *cipher, size_t &cipher_len, size_t max_cipher_len, const uint8_t *plain, size_t plain_len,
                     uint64_t pkt_num, const uint8_t *ad, size_t ad_len, QUICKeyPhase phase) const
diff --git a/iocore/net/quic/QUICCrypto.h b/iocore/net/quic/QUICCrypto.h
index f4c7fc9..5617e61 100644
--- a/iocore/net/quic/QUICCrypto.h
+++ b/iocore/net/quic/QUICCrypto.h
@@ -78,6 +78,9 @@ public:
   int update_client_keymaterial();
   int update_server_keymaterial();
 
+  // FIXME SSL handle should not be exported
+  SSL *ssl_handle();
+
 private:
   int _export_secret(uint8_t *dst, size_t dst_len, const char *label, size_t label_len) const;
   int _export_client_keymaterial(size_t secret_len, size_t key_len, size_t iv_len);
diff --git a/iocore/net/quic/QUICGlobals.cc b/iocore/net/quic/QUICGlobals.cc
index ca6e151..b8dd77d 100644
--- a/iocore/net/quic/QUICGlobals.cc
+++ b/iocore/net/quic/QUICGlobals.cc
@@ -21,6 +21,27 @@
  *  limitations under the License.
  */
 
+#include <cstring>
 #include "QUICGlobals.h"
+#include "P_QUICNetVConnection.h"
+#include "P_SSLNextProtocolSet.h"
 
 int QUIC::ssl_quic_vc_index = -1;
+
+int
+QUIC::ssl_select_next_protocol(SSL *ssl, const unsigned char **out, unsigned char *outlen, const unsigned char *in, unsigned inlen,
+                               void *)
+{
+  const unsigned char *npn;
+  unsigned npnsz           = 0;
+  QUICNetVConnection *qnvc = static_cast<QUICNetVConnection *>(SSL_get_ex_data(ssl, QUIC::ssl_quic_vc_index));
+
+  qnvc->next_protocol_set()->advertiseProtocols(&npn, &npnsz);
+  if (SSL_select_next_proto((unsigned char **)out, outlen, npn, npnsz, in, inlen) == OPENSSL_NPN_NEGOTIATED) {
+    return SSL_TLSEXT_ERR_OK;
+  }
+
+  *out    = nullptr;
+  *outlen = 0;
+  return SSL_TLSEXT_ERR_NOACK;
+}
diff --git a/iocore/net/quic/QUICGlobals.h b/iocore/net/quic/QUICGlobals.h
index 2dcdef3..e1d2b4a 100644
--- a/iocore/net/quic/QUICGlobals.h
+++ b/iocore/net/quic/QUICGlobals.h
@@ -34,4 +34,8 @@ public:
     ssl_quic_vc_index = SSL_get_ex_new_index(0, (void *)"NetVC index", nullptr, nullptr, nullptr);
   }
   static int ssl_quic_vc_index;
+
+  // SSL callbacks
+  static int ssl_select_next_protocol(SSL *ssl, const unsigned char **out, unsigned char *outlen, const unsigned char *in,
+                                      unsigned inlen, void *);
 };
diff --git a/iocore/net/quic/QUICHandshake.cc b/iocore/net/quic/QUICHandshake.cc
index a81daa3..8426138 100644
--- a/iocore/net/quic/QUICHandshake.cc
+++ b/iocore/net/quic/QUICHandshake.cc
@@ -60,11 +60,10 @@ QUICHandshake::is_completed()
   return crypto->is_handshake_finished();
 }
 
-const uint8_t *
-QUICHandshake::negotiated_application_name()
+void
+QUICHandshake::negotiated_application_name(const uint8_t **name, unsigned int *len)
 {
-  // TODO Use the protocol name negotiated on ALPN
-  return reinterpret_cast<const uint8_t *>("hq");
+  SSL_get0_alpn_selected(this->_crypto->ssl_handle(), name, len);
 }
 
 int
diff --git a/iocore/net/quic/QUICHandshake.h b/iocore/net/quic/QUICHandshake.h
index 64074a0..3a501f0 100644
--- a/iocore/net/quic/QUICHandshake.h
+++ b/iocore/net/quic/QUICHandshake.h
@@ -54,7 +54,7 @@ public:
   int state_complete(int event, void *data);
   int state_closed(int event, void *data);
   bool is_completed();
-  const uint8_t *negotiated_application_name();
+  void negotiated_application_name(const uint8_t **name, unsigned int *len);
 
 private:
   QUICCrypto *_crypto = nullptr;
diff --git a/lib/records/I_RecHttp.h b/lib/records/I_RecHttp.h
index 066486a..99e38ea 100644
--- a/lib/records/I_RecHttp.h
+++ b/lib/records/I_RecHttp.h
@@ -135,6 +135,7 @@ extern SessionProtocolSet HTTP_PROTOCOL_SET;
 extern SessionProtocolSet HTTP2_PROTOCOL_SET;
 extern SessionProtocolSet DEFAULT_NON_TLS_SESSION_PROTOCOL_SET;
 extern SessionProtocolSet DEFAULT_TLS_SESSION_PROTOCOL_SET;
+extern SessionProtocolSet DEFAULT_QUIC_SESSION_PROTOCOL_SET;
 
 const char *RecNormalizeProtoTag(const char *tag);
 
diff --git a/lib/records/RecHttp.cc b/lib/records/RecHttp.cc
index d302499..b2b3f3a 100644
--- a/lib/records/RecHttp.cc
+++ b/lib/records/RecHttp.cc
@@ -40,6 +40,7 @@ const char *const TS_ALPN_PROTOCOL_HTTP_0_9 = IP_PROTO_TAG_HTTP_0_9.ptr();
 const char *const TS_ALPN_PROTOCOL_HTTP_1_0 = IP_PROTO_TAG_HTTP_1_0.ptr();
 const char *const TS_ALPN_PROTOCOL_HTTP_1_1 = IP_PROTO_TAG_HTTP_1_1.ptr();
 const char *const TS_ALPN_PROTOCOL_HTTP_2_0 = IP_PROTO_TAG_HTTP_2_0.ptr();
+const char *const TS_ALPN_PROTOCOL_HTTP_QUIC = IP_PROTO_TAG_HTTP_QUIC.ptr();
 
 const char *const TS_ALPN_PROTOCOL_GROUP_HTTP  = "http";
 const char *const TS_ALPN_PROTOCOL_GROUP_HTTP2 = "http2";
@@ -47,6 +48,7 @@ const char *const TS_ALPN_PROTOCOL_GROUP_HTTP2 = "http2";
 const char *const TS_PROTO_TAG_HTTP_1_0 = TS_ALPN_PROTOCOL_HTTP_1_0;
 const char *const TS_PROTO_TAG_HTTP_1_1 = TS_ALPN_PROTOCOL_HTTP_1_1;
 const char *const TS_PROTO_TAG_HTTP_2_0 = TS_ALPN_PROTOCOL_HTTP_2_0;
+const char *const TS_PROTO_TAG_HTTP_QUIC = TS_ALPN_PROTOCOL_HTTP_QUIC;
 const char *const TS_PROTO_TAG_TLS_1_3  = IP_PROTO_TAG_TLS_1_3.ptr();
 const char *const TS_PROTO_TAG_TLS_1_2  = IP_PROTO_TAG_TLS_1_2.ptr();
 const char *const TS_PROTO_TAG_TLS_1_1  = IP_PROTO_TAG_TLS_1_1.ptr();
@@ -63,12 +65,14 @@ int TS_ALPN_PROTOCOL_INDEX_HTTP_0_9 = SessionProtocolNameRegistry::INVALID;
 int TS_ALPN_PROTOCOL_INDEX_HTTP_1_0 = SessionProtocolNameRegistry::INVALID;
 int TS_ALPN_PROTOCOL_INDEX_HTTP_1_1 = SessionProtocolNameRegistry::INVALID;
 int TS_ALPN_PROTOCOL_INDEX_HTTP_2_0 = SessionProtocolNameRegistry::INVALID;
+int TS_ALPN_PROTOCOL_INDEX_HTTP_QUIC = SessionProtocolNameRegistry::INVALID;
 
 // Predefined protocol sets for ease of use.
 SessionProtocolSet HTTP_PROTOCOL_SET;
 SessionProtocolSet HTTP2_PROTOCOL_SET;
 SessionProtocolSet DEFAULT_NON_TLS_SESSION_PROTOCOL_SET;
 SessionProtocolSet DEFAULT_TLS_SESSION_PROTOCOL_SET;
+SessionProtocolSet DEFAULT_QUIC_SESSION_PROTOCOL_SET;
 
 void
 RecHttpLoadIp(const char *value_name, IpAddr &ip4, IpAddr &ip6)
@@ -432,7 +436,13 @@ HttpProxyPort::processOptions(const char *opts)
 
   // Set the default session protocols.
   if (!sp_set_p) {
-    m_session_protocol_preference = this->isSSL() ? DEFAULT_TLS_SESSION_PROTOCOL_SET : DEFAULT_NON_TLS_SESSION_PROTOCOL_SET;
+    if (this->isSSL()) {
+      m_session_protocol_preference = DEFAULT_TLS_SESSION_PROTOCOL_SET;
+    } else if (this->isQUIC()) {
+      m_session_protocol_preference = DEFAULT_QUIC_SESSION_PROTOCOL_SET;
+    } else {
+      m_session_protocol_preference = DEFAULT_NON_TLS_SESSION_PROTOCOL_SET;
+    }
   }
 
   return zret;
@@ -587,6 +597,8 @@ HttpProxyPort::print(char *out, size_t n)
     sp_set.markOut(DEFAULT_NON_TLS_SESSION_PROTOCOL_SET);
   } else if (sp_set == DEFAULT_TLS_SESSION_PROTOCOL_SET && this->isSSL()) {
     sp_set.markOut(DEFAULT_TLS_SESSION_PROTOCOL_SET);
+  } else if (sp_set == DEFAULT_QUIC_SESSION_PROTOCOL_SET && this->isQUIC()) {
+    sp_set.markOut(DEFAULT_QUIC_SESSION_PROTOCOL_SET);
   }
 
   // pull out groups.
@@ -644,6 +656,7 @@ ts_session_protocol_well_known_name_indices_init()
   TS_ALPN_PROTOCOL_INDEX_HTTP_1_0 = globalSessionProtocolNameRegistry.toIndexConst(TS_ALPN_PROTOCOL_HTTP_1_0);
   TS_ALPN_PROTOCOL_INDEX_HTTP_1_1 = globalSessionProtocolNameRegistry.toIndexConst(TS_ALPN_PROTOCOL_HTTP_1_1);
   TS_ALPN_PROTOCOL_INDEX_HTTP_2_0 = globalSessionProtocolNameRegistry.toIndexConst(TS_ALPN_PROTOCOL_HTTP_2_0);
+  TS_ALPN_PROTOCOL_INDEX_HTTP_QUIC = globalSessionProtocolNameRegistry.toIndexConst(TS_ALPN_PROTOCOL_HTTP_QUIC);
 
   // Now do the predefined protocol sets.
   HTTP_PROTOCOL_SET.markIn(TS_ALPN_PROTOCOL_INDEX_HTTP_0_9);
@@ -652,6 +665,9 @@ ts_session_protocol_well_known_name_indices_init()
   HTTP2_PROTOCOL_SET.markIn(TS_ALPN_PROTOCOL_INDEX_HTTP_2_0);
 
   DEFAULT_TLS_SESSION_PROTOCOL_SET.markAllIn();
+  DEFAULT_TLS_SESSION_PROTOCOL_SET.markOut(TS_ALPN_PROTOCOL_INDEX_HTTP_QUIC);
+
+  DEFAULT_QUIC_SESSION_PROTOCOL_SET.markIn(TS_ALPN_PROTOCOL_INDEX_HTTP_QUIC);
 
   DEFAULT_NON_TLS_SESSION_PROTOCOL_SET = HTTP_PROTOCOL_SET;
 
@@ -659,6 +675,7 @@ ts_session_protocol_well_known_name_indices_init()
   ink_hash_table_insert(TSProtoTags, TS_PROTO_TAG_HTTP_1_0, reinterpret_cast<void *>(const_cast<char *>(TS_PROTO_TAG_HTTP_1_0)));
   ink_hash_table_insert(TSProtoTags, TS_PROTO_TAG_HTTP_1_1, reinterpret_cast<void *>(const_cast<char *>(TS_PROTO_TAG_HTTP_1_1)));
   ink_hash_table_insert(TSProtoTags, TS_PROTO_TAG_HTTP_2_0, reinterpret_cast<void *>(const_cast<char *>(TS_PROTO_TAG_HTTP_2_0)));
+  ink_hash_table_insert(TSProtoTags, TS_PROTO_TAG_HTTP_QUIC, reinterpret_cast<void *>(const_cast<char *>(TS_PROTO_TAG_HTTP_QUIC)));
   ink_hash_table_insert(TSProtoTags, TS_PROTO_TAG_TLS_1_3, reinterpret_cast<void *>(const_cast<char *>(TS_PROTO_TAG_TLS_1_3)));
   ink_hash_table_insert(TSProtoTags, TS_PROTO_TAG_TLS_1_2, reinterpret_cast<void *>(const_cast<char *>(TS_PROTO_TAG_TLS_1_2)));
   ink_hash_table_insert(TSProtoTags, TS_PROTO_TAG_TLS_1_1, reinterpret_cast<void *>(const_cast<char *>(TS_PROTO_TAG_TLS_1_1)));
diff --git a/lib/ts/apidefs.h.in b/lib/ts/apidefs.h.in
index eb69a70..79fc0f7 100644
--- a/lib/ts/apidefs.h.in
+++ b/lib/ts/apidefs.h.in
@@ -1161,11 +1161,13 @@ extern tsapi const char *const TS_ALPN_PROTOCOL_HTTP_0_9;
 extern tsapi const char *const TS_ALPN_PROTOCOL_HTTP_1_0;
 extern tsapi const char *const TS_ALPN_PROTOCOL_HTTP_1_1;
 extern tsapi const char *const TS_ALPN_PROTOCOL_HTTP_2_0;
+extern tsapi const char *const TS_ALPN_PROTOCOL_HTTP_QUIC;
 
 extern tsapi int TS_ALPN_PROTOCOL_INDEX_HTTP_0_9;
 extern tsapi int TS_ALPN_PROTOCOL_INDEX_HTTP_1_0;
 extern tsapi int TS_ALPN_PROTOCOL_INDEX_HTTP_1_1;
 extern tsapi int TS_ALPN_PROTOCOL_INDEX_HTTP_2_0;
+extern tsapi int TS_ALPN_PROTOCOL_INDEX_HTTP_QUIC;
 
 extern tsapi const char *const TS_ALPN_PROTOCOL_GROUP_HTTP;
 extern tsapi const char *const TS_ALPN_PROTOCOL_GROUP_HTTP2;
@@ -1173,6 +1175,7 @@ extern tsapi const char *const TS_ALPN_PROTOCOL_GROUP_HTTP2;
 extern tsapi const char *const TS_PROTO_TAG_HTTP_1_0;
 extern tsapi const char *const TS_PROTO_TAG_HTTP_1_1;
 extern tsapi const char *const TS_PROTO_TAG_HTTP_2_0;
+extern tsapi const char *const TS_PROTO_TAG_HTTP_QUIC;
 extern tsapi const char *const TS_PROTO_TAG_TLS_1_3;
 extern tsapi const char *const TS_PROTO_TAG_TLS_1_2;
 extern tsapi const char *const TS_PROTO_TAG_TLS_1_1;
diff --git a/lib/ts/ink_inet.cc b/lib/ts/ink_inet.cc
index 2e940c6..8247cb4 100644
--- a/lib/ts/ink_inet.cc
+++ b/lib/ts/ink_inet.cc
@@ -44,6 +44,7 @@ const ts::StringView IP_PROTO_TAG_HTTP_0_9("http/0.9", ts::StringView::literal);
 const ts::StringView IP_PROTO_TAG_HTTP_1_0("http/1.0", ts::StringView::literal);
 const ts::StringView IP_PROTO_TAG_HTTP_1_1("http/1.1", ts::StringView::literal);
 const ts::StringView IP_PROTO_TAG_HTTP_2_0("h2", ts::StringView::literal); // HTTP/2 over TLS
+const ts::StringView IP_PROTO_TAG_HTTP_QUIC("hq-05", ts::StringView::literal); // HTTP over QUIC
 
 uint32_t
 ink_inet_addr(const char *s)
diff --git a/lib/ts/ink_inet.h b/lib/ts/ink_inet.h
index 2f0c757..bca32a0 100644
--- a/lib/ts/ink_inet.h
+++ b/lib/ts/ink_inet.h
@@ -58,6 +58,7 @@ extern const ts::StringView IP_PROTO_TAG_HTTP_0_9;
 extern const ts::StringView IP_PROTO_TAG_HTTP_1_0;
 extern const ts::StringView IP_PROTO_TAG_HTTP_1_1;
 extern const ts::StringView IP_PROTO_TAG_HTTP_2_0;
+extern const ts::StringView IP_PROTO_TAG_HTTP_QUIC;
 
 struct IpAddr; // forward declare.
 
diff --git a/proxy/http/HttpProxyServerMain.cc b/proxy/http/HttpProxyServerMain.cc
index 6e27716..1ee1b0f 100644
--- a/proxy/http/HttpProxyServerMain.cc
+++ b/proxy/http/HttpProxyServerMain.cc
@@ -224,8 +224,11 @@ MakeHttpProxyAcceptor(HttpProxyAcceptor &acceptor, HttpProxyPort &port, unsigned
 #if TS_USE_QUIC == 1
   } else if (port.isQUIC()) {
     // HTTP/QUIC
-    HQSessionAccept *hq = new HQSessionAccept(accept_opt);
-    acceptor._accept    = hq;
+    if (port.m_session_protocol_preference.contains(TS_ALPN_PROTOCOL_INDEX_HTTP_QUIC)) {
+      HQSessionAccept *hq = new HQSessionAccept(accept_opt);
+      // FIXME hq should be registered to QUICNextProtocolAccept like SSL
+      acceptor._accept    = hq;
+    }
 #endif
   } else {
     acceptor._accept = probe;

-- 
To stop receiving notification emails like this one, please contact
['"commits@trafficserver.apache.org" <co...@trafficserver.apache.org>'].