mirror of
https://github.com/klzgrad/naiveproxy.git
synced 2024-12-01 17:56:10 +03:00
529 lines
18 KiB
C++
529 lines
18 KiB
C++
// Copyright 2012 The Chromium Authors
|
|
// Use of this source code is governed by a BSD-style license that can be
|
|
// found in the LICENSE file.
|
|
|
|
#include "net/http/http_response_info.h"
|
|
|
|
#include "base/logging.h"
|
|
#include "base/numerics/safe_conversions.h"
|
|
#include "base/pickle.h"
|
|
#include "base/time/time.h"
|
|
#include "net/base/net_errors.h"
|
|
#include "net/cert/sct_status_flags.h"
|
|
#include "net/cert/signed_certificate_timestamp.h"
|
|
#include "net/cert/x509_certificate.h"
|
|
#include "net/http/http_response_headers.h"
|
|
#include "net/ssl/ssl_cert_request_info.h"
|
|
#include "net/ssl/ssl_connection_status_flags.h"
|
|
#include "net/third_party/quiche/src/quiche/quic/core/quic_versions.h"
|
|
#include "third_party/abseil-cpp/absl/types/optional.h"
|
|
#include "third_party/boringssl/src/include/openssl/ssl.h"
|
|
|
|
using base::Time;
|
|
|
|
namespace net {
|
|
|
|
namespace {
|
|
|
|
bool KeyExchangeGroupIsValid(int ssl_connection_status) {
|
|
// TLS 1.3 and later always treat the field correctly.
|
|
if (SSLConnectionStatusToVersion(ssl_connection_status) >=
|
|
SSL_CONNECTION_VERSION_TLS1_3) {
|
|
return true;
|
|
}
|
|
|
|
// Prior to TLS 1.3, only ECDHE ciphers have groups.
|
|
const SSL_CIPHER* cipher = SSL_get_cipher_by_value(
|
|
SSLConnectionStatusToCipherSuite(ssl_connection_status));
|
|
return cipher && SSL_CIPHER_get_kx_nid(cipher) == NID_kx_ecdhe;
|
|
}
|
|
|
|
} // namespace
|
|
|
|
// These values can be bit-wise combined to form the flags field of the
|
|
// serialized HttpResponseInfo.
|
|
enum {
|
|
// The version of the response info used when persisting response info.
|
|
RESPONSE_INFO_VERSION = 3,
|
|
|
|
// The minimum version supported for deserializing response info.
|
|
RESPONSE_INFO_MINIMUM_VERSION = 3,
|
|
|
|
// We reserve up to 8 bits for the version number.
|
|
RESPONSE_INFO_VERSION_MASK = 0xFF,
|
|
|
|
// This bit is set if the response info has a cert at the end.
|
|
// Version 1 serialized only the end-entity certificate, while subsequent
|
|
// versions include the available certificate chain.
|
|
RESPONSE_INFO_HAS_CERT = 1 << 8,
|
|
|
|
// This bit was historically set if the response info had a security-bits
|
|
// field (security strength, in bits, of the SSL connection) at the end.
|
|
RESPONSE_INFO_HAS_SECURITY_BITS = 1 << 9,
|
|
|
|
// This bit is set if the response info has a cert status at the end.
|
|
RESPONSE_INFO_HAS_CERT_STATUS = 1 << 10,
|
|
|
|
// This bit is set if the response info has vary header data.
|
|
RESPONSE_INFO_HAS_VARY_DATA = 1 << 11,
|
|
|
|
// This bit is set if the request was cancelled before completion.
|
|
RESPONSE_INFO_TRUNCATED = 1 << 12,
|
|
|
|
// This bit is set if the response was received via SPDY.
|
|
RESPONSE_INFO_WAS_SPDY = 1 << 13,
|
|
|
|
// This bit is set if the request has ALPN negotiated.
|
|
RESPONSE_INFO_WAS_ALPN = 1 << 14,
|
|
|
|
// This bit is set if the request was fetched via an explicit proxy.
|
|
RESPONSE_INFO_WAS_PROXY = 1 << 15,
|
|
|
|
// This bit is set if the response info has an SSL connection status field.
|
|
// This contains the ciphersuite used to fetch the resource as well as the
|
|
// protocol version, compression method and whether SSLv3 fallback was used.
|
|
RESPONSE_INFO_HAS_SSL_CONNECTION_STATUS = 1 << 16,
|
|
|
|
// This bit is set if the response info has protocol version.
|
|
RESPONSE_INFO_HAS_ALPN_NEGOTIATED_PROTOCOL = 1 << 17,
|
|
|
|
// This bit is set if the response info has connection info.
|
|
RESPONSE_INFO_HAS_CONNECTION_INFO = 1 << 18,
|
|
|
|
// This bit is set if the request has http authentication.
|
|
RESPONSE_INFO_USE_HTTP_AUTHENTICATION = 1 << 19,
|
|
|
|
// This bit is set if ssl_info has SCTs.
|
|
RESPONSE_INFO_HAS_SIGNED_CERTIFICATE_TIMESTAMPS = 1 << 20,
|
|
|
|
RESPONSE_INFO_UNUSED_SINCE_PREFETCH = 1 << 21,
|
|
|
|
// This bit is set if the response has a key exchange group.
|
|
RESPONSE_INFO_HAS_KEY_EXCHANGE_GROUP = 1 << 22,
|
|
|
|
// This bit is set if ssl_info recorded that PKP was bypassed due to a local
|
|
// trust anchor.
|
|
RESPONSE_INFO_PKP_BYPASSED = 1 << 23,
|
|
|
|
// This bit is set if stale_revalidate_time is stored.
|
|
RESPONSE_INFO_HAS_STALENESS = 1 << 24,
|
|
|
|
// This bit is set if the response has a peer signature algorithm.
|
|
RESPONSE_INFO_HAS_PEER_SIGNATURE_ALGORITHM = 1 << 25,
|
|
|
|
// This bit is set if the response is a prefetch whose reuse should be
|
|
// restricted in some way.
|
|
RESPONSE_INFO_RESTRICTED_PREFETCH = 1 << 26,
|
|
|
|
// This bit is set if the response has a nonempty `dns_aliases` entry.
|
|
RESPONSE_INFO_HAS_DNS_ALIASES = 1 << 27,
|
|
|
|
// This bit is now unused. It may be set on existing entries. Previously it
|
|
// was set for an entry in the single-keyed cache that had been marked
|
|
// unusable due to the cache transparency checksum not matching.
|
|
RESPONSE_INFO_UNUSED_WAS_SINGLE_KEYED_CACHE_ENTRY_UNUSABLE = 1 << 28,
|
|
|
|
// This bit is set if the response has `encrypted_client_hello` set.
|
|
RESPONSE_INFO_ENCRYPTED_CLIENT_HELLO = 1 << 29,
|
|
|
|
// This bit is set if the response has `browser_run_id` set.
|
|
RESPONSE_INFO_BROWSER_RUN_ID = 1 << 30,
|
|
|
|
// This bit is set if the response has extra bit set.
|
|
RESPONSE_INFO_HAS_EXTRA_FLAGS = 1 << 31,
|
|
};
|
|
|
|
// These values can be bit-wise combined to form the extra flags field of the
|
|
// serialized HttpResponseInfo.
|
|
enum {
|
|
// This bit is set if the request usd a shared dictionary for decoding its
|
|
// body.
|
|
RESPONSE_EXTRA_INFO_DID_USE_SHARED_DICTIONARY = 1,
|
|
};
|
|
|
|
HttpResponseInfo::HttpResponseInfo() = default;
|
|
|
|
HttpResponseInfo::HttpResponseInfo(const HttpResponseInfo& rhs) = default;
|
|
|
|
HttpResponseInfo::~HttpResponseInfo() = default;
|
|
|
|
HttpResponseInfo& HttpResponseInfo::operator=(const HttpResponseInfo& rhs) =
|
|
default;
|
|
|
|
bool HttpResponseInfo::InitFromPickle(const base::Pickle& pickle,
|
|
bool* response_truncated) {
|
|
base::PickleIterator iter(pickle);
|
|
|
|
// Read flags and verify version
|
|
int flags;
|
|
int extra_flags = 0;
|
|
if (!iter.ReadInt(&flags))
|
|
return false;
|
|
if (flags & RESPONSE_INFO_HAS_EXTRA_FLAGS) {
|
|
if (!iter.ReadInt(&extra_flags)) {
|
|
return false;
|
|
}
|
|
}
|
|
int version = flags & RESPONSE_INFO_VERSION_MASK;
|
|
if (version < RESPONSE_INFO_MINIMUM_VERSION ||
|
|
version > RESPONSE_INFO_VERSION) {
|
|
DLOG(ERROR) << "unexpected response info version: " << version;
|
|
return false;
|
|
}
|
|
|
|
// Read request-time
|
|
int64_t time_val;
|
|
if (!iter.ReadInt64(&time_val))
|
|
return false;
|
|
request_time = Time::FromInternalValue(time_val);
|
|
was_cached = true; // Set status to show cache resurrection.
|
|
|
|
// Read response-time
|
|
if (!iter.ReadInt64(&time_val))
|
|
return false;
|
|
response_time = Time::FromInternalValue(time_val);
|
|
|
|
// Read response-headers
|
|
headers = base::MakeRefCounted<HttpResponseHeaders>(&iter);
|
|
if (headers->response_code() == -1)
|
|
return false;
|
|
|
|
// Read ssl-info
|
|
if (flags & RESPONSE_INFO_HAS_CERT) {
|
|
ssl_info.cert = X509Certificate::CreateFromPickle(&iter);
|
|
if (!ssl_info.cert.get())
|
|
return false;
|
|
}
|
|
if (flags & RESPONSE_INFO_HAS_CERT_STATUS) {
|
|
CertStatus cert_status;
|
|
if (!iter.ReadUInt32(&cert_status))
|
|
return false;
|
|
ssl_info.cert_status = cert_status;
|
|
}
|
|
if (flags & RESPONSE_INFO_HAS_SECURITY_BITS) {
|
|
// The security_bits field has been removed from ssl_info. For backwards
|
|
// compatibility, we should still read the value out of iter.
|
|
int security_bits;
|
|
if (!iter.ReadInt(&security_bits))
|
|
return false;
|
|
}
|
|
|
|
if (flags & RESPONSE_INFO_HAS_SSL_CONNECTION_STATUS) {
|
|
int connection_status;
|
|
if (!iter.ReadInt(&connection_status))
|
|
return false;
|
|
|
|
// SSLv3 is gone, so drop cached entries that were loaded over SSLv3.
|
|
if (SSLConnectionStatusToVersion(connection_status) ==
|
|
SSL_CONNECTION_VERSION_SSL3) {
|
|
return false;
|
|
}
|
|
ssl_info.connection_status = connection_status;
|
|
}
|
|
|
|
// Signed Certificate Timestamps are no longer persisted to the cache, so
|
|
// ignore them when reading them out.
|
|
if (flags & RESPONSE_INFO_HAS_SIGNED_CERTIFICATE_TIMESTAMPS) {
|
|
int num_scts;
|
|
if (!iter.ReadInt(&num_scts))
|
|
return false;
|
|
for (int i = 0; i < num_scts; ++i) {
|
|
scoped_refptr<ct::SignedCertificateTimestamp> sct(
|
|
ct::SignedCertificateTimestamp::CreateFromPickle(&iter));
|
|
uint16_t status;
|
|
if (!sct.get() || !iter.ReadUInt16(&status))
|
|
return false;
|
|
}
|
|
}
|
|
|
|
// Read vary-data
|
|
if (flags & RESPONSE_INFO_HAS_VARY_DATA) {
|
|
if (!vary_data.InitFromPickle(&iter))
|
|
return false;
|
|
}
|
|
|
|
// Read socket_address.
|
|
std::string socket_address_host;
|
|
if (!iter.ReadString(&socket_address_host))
|
|
return false;
|
|
// If the host was written, we always expect the port to follow.
|
|
uint16_t socket_address_port;
|
|
if (!iter.ReadUInt16(&socket_address_port))
|
|
return false;
|
|
|
|
IPAddress ip_address;
|
|
if (ip_address.AssignFromIPLiteral(socket_address_host)) {
|
|
remote_endpoint = IPEndPoint(ip_address, socket_address_port);
|
|
} else if (ParseURLHostnameToAddress(socket_address_host, &ip_address)) {
|
|
remote_endpoint = IPEndPoint(ip_address, socket_address_port);
|
|
}
|
|
|
|
// Read protocol-version.
|
|
if (flags & RESPONSE_INFO_HAS_ALPN_NEGOTIATED_PROTOCOL) {
|
|
if (!iter.ReadString(&alpn_negotiated_protocol))
|
|
return false;
|
|
}
|
|
|
|
// Read connection info.
|
|
if (flags & RESPONSE_INFO_HAS_CONNECTION_INFO) {
|
|
int value;
|
|
if (!iter.ReadInt(&value))
|
|
return false;
|
|
|
|
if (value > static_cast<int>(HttpConnectionInfo::kUNKNOWN) &&
|
|
value <= static_cast<int>(HttpConnectionInfo::kMaxValue)) {
|
|
connection_info = static_cast<HttpConnectionInfo>(value);
|
|
}
|
|
}
|
|
|
|
// Read key_exchange_group
|
|
if (flags & RESPONSE_INFO_HAS_KEY_EXCHANGE_GROUP) {
|
|
int key_exchange_group;
|
|
if (!iter.ReadInt(&key_exchange_group))
|
|
return false;
|
|
|
|
// Historically, the key_exchange_group field was key_exchange_info which
|
|
// conflated a number of different values based on the cipher suite, so some
|
|
// values must be discarded. See https://crbug.com/639421.
|
|
if (KeyExchangeGroupIsValid(ssl_info.connection_status))
|
|
ssl_info.key_exchange_group = key_exchange_group;
|
|
}
|
|
|
|
// Read staleness time.
|
|
if (flags & RESPONSE_INFO_HAS_STALENESS) {
|
|
if (!iter.ReadInt64(&time_val))
|
|
return false;
|
|
stale_revalidate_timeout = base::Time() + base::Microseconds(time_val);
|
|
}
|
|
|
|
was_fetched_via_spdy = (flags & RESPONSE_INFO_WAS_SPDY) != 0;
|
|
|
|
was_alpn_negotiated = (flags & RESPONSE_INFO_WAS_ALPN) != 0;
|
|
|
|
was_fetched_via_proxy = (flags & RESPONSE_INFO_WAS_PROXY) != 0;
|
|
|
|
*response_truncated = (flags & RESPONSE_INFO_TRUNCATED) != 0;
|
|
|
|
did_use_http_auth = (flags & RESPONSE_INFO_USE_HTTP_AUTHENTICATION) != 0;
|
|
|
|
unused_since_prefetch = (flags & RESPONSE_INFO_UNUSED_SINCE_PREFETCH) != 0;
|
|
|
|
restricted_prefetch = (flags & RESPONSE_INFO_RESTRICTED_PREFETCH) != 0;
|
|
|
|
// RESPONSE_INFO_UNUSED_WAS_SINGLE_KEYED_CACHE_ENTRY_UNUSABLE is unused.
|
|
|
|
ssl_info.pkp_bypassed = (flags & RESPONSE_INFO_PKP_BYPASSED) != 0;
|
|
|
|
// Read peer_signature_algorithm.
|
|
if (flags & RESPONSE_INFO_HAS_PEER_SIGNATURE_ALGORITHM) {
|
|
int peer_signature_algorithm;
|
|
if (!iter.ReadInt(&peer_signature_algorithm) ||
|
|
!base::IsValueInRangeForNumericType<uint16_t>(
|
|
peer_signature_algorithm)) {
|
|
return false;
|
|
}
|
|
ssl_info.peer_signature_algorithm =
|
|
base::checked_cast<uint16_t>(peer_signature_algorithm);
|
|
}
|
|
|
|
// Read DNS aliases.
|
|
if (flags & RESPONSE_INFO_HAS_DNS_ALIASES) {
|
|
int num_aliases;
|
|
if (!iter.ReadInt(&num_aliases))
|
|
return false;
|
|
|
|
std::string alias;
|
|
for (int i = 0; i < num_aliases; i++) {
|
|
if (!iter.ReadString(&alias))
|
|
return false;
|
|
dns_aliases.insert(alias);
|
|
}
|
|
}
|
|
|
|
ssl_info.encrypted_client_hello =
|
|
(flags & RESPONSE_INFO_ENCRYPTED_CLIENT_HELLO) != 0;
|
|
|
|
// Read browser_run_id.
|
|
if (flags & RESPONSE_INFO_BROWSER_RUN_ID) {
|
|
int64_t id;
|
|
if (!iter.ReadInt64(&id))
|
|
return false;
|
|
browser_run_id = absl::make_optional(id);
|
|
}
|
|
|
|
did_use_shared_dictionary =
|
|
(extra_flags & RESPONSE_EXTRA_INFO_DID_USE_SHARED_DICTIONARY) != 0;
|
|
return true;
|
|
}
|
|
|
|
void HttpResponseInfo::Persist(base::Pickle* pickle,
|
|
bool skip_transient_headers,
|
|
bool response_truncated) const {
|
|
int flags = RESPONSE_INFO_VERSION;
|
|
int extra_flags = 0;
|
|
if (ssl_info.is_valid()) {
|
|
flags |= RESPONSE_INFO_HAS_CERT;
|
|
flags |= RESPONSE_INFO_HAS_CERT_STATUS;
|
|
if (ssl_info.key_exchange_group != 0)
|
|
flags |= RESPONSE_INFO_HAS_KEY_EXCHANGE_GROUP;
|
|
if (ssl_info.connection_status != 0)
|
|
flags |= RESPONSE_INFO_HAS_SSL_CONNECTION_STATUS;
|
|
if (ssl_info.peer_signature_algorithm != 0)
|
|
flags |= RESPONSE_INFO_HAS_PEER_SIGNATURE_ALGORITHM;
|
|
}
|
|
if (vary_data.is_valid())
|
|
flags |= RESPONSE_INFO_HAS_VARY_DATA;
|
|
if (response_truncated)
|
|
flags |= RESPONSE_INFO_TRUNCATED;
|
|
if (was_fetched_via_spdy)
|
|
flags |= RESPONSE_INFO_WAS_SPDY;
|
|
if (was_alpn_negotiated) {
|
|
flags |= RESPONSE_INFO_WAS_ALPN;
|
|
flags |= RESPONSE_INFO_HAS_ALPN_NEGOTIATED_PROTOCOL;
|
|
}
|
|
if (was_fetched_via_proxy)
|
|
flags |= RESPONSE_INFO_WAS_PROXY;
|
|
if (connection_info != HttpConnectionInfo::kUNKNOWN) {
|
|
flags |= RESPONSE_INFO_HAS_CONNECTION_INFO;
|
|
}
|
|
if (did_use_http_auth)
|
|
flags |= RESPONSE_INFO_USE_HTTP_AUTHENTICATION;
|
|
if (unused_since_prefetch)
|
|
flags |= RESPONSE_INFO_UNUSED_SINCE_PREFETCH;
|
|
if (restricted_prefetch)
|
|
flags |= RESPONSE_INFO_RESTRICTED_PREFETCH;
|
|
// RESPONSE_INFO_UNUSED_WAS_SINGLE_KEYED_CACHE_ENTRY_UNUSABLE is not used.
|
|
if (ssl_info.pkp_bypassed)
|
|
flags |= RESPONSE_INFO_PKP_BYPASSED;
|
|
if (!stale_revalidate_timeout.is_null())
|
|
flags |= RESPONSE_INFO_HAS_STALENESS;
|
|
if (!dns_aliases.empty())
|
|
flags |= RESPONSE_INFO_HAS_DNS_ALIASES;
|
|
if (ssl_info.encrypted_client_hello)
|
|
flags |= RESPONSE_INFO_ENCRYPTED_CLIENT_HELLO;
|
|
if (browser_run_id.has_value())
|
|
flags |= RESPONSE_INFO_BROWSER_RUN_ID;
|
|
|
|
if (did_use_shared_dictionary) {
|
|
extra_flags |= RESPONSE_EXTRA_INFO_DID_USE_SHARED_DICTIONARY;
|
|
}
|
|
|
|
if (extra_flags) {
|
|
flags |= RESPONSE_INFO_HAS_EXTRA_FLAGS;
|
|
}
|
|
|
|
pickle->WriteInt(flags);
|
|
if (extra_flags) {
|
|
pickle->WriteInt(extra_flags);
|
|
}
|
|
pickle->WriteInt64(request_time.ToInternalValue());
|
|
pickle->WriteInt64(response_time.ToInternalValue());
|
|
|
|
HttpResponseHeaders::PersistOptions persist_options =
|
|
HttpResponseHeaders::PERSIST_RAW;
|
|
|
|
if (skip_transient_headers) {
|
|
persist_options = HttpResponseHeaders::PERSIST_SANS_COOKIES |
|
|
HttpResponseHeaders::PERSIST_SANS_CHALLENGES |
|
|
HttpResponseHeaders::PERSIST_SANS_HOP_BY_HOP |
|
|
HttpResponseHeaders::PERSIST_SANS_NON_CACHEABLE |
|
|
HttpResponseHeaders::PERSIST_SANS_RANGES |
|
|
HttpResponseHeaders::PERSIST_SANS_SECURITY_STATE;
|
|
}
|
|
|
|
headers->Persist(pickle, persist_options);
|
|
|
|
if (ssl_info.is_valid()) {
|
|
ssl_info.cert->Persist(pickle);
|
|
pickle->WriteUInt32(ssl_info.cert_status);
|
|
if (ssl_info.connection_status != 0)
|
|
pickle->WriteInt(ssl_info.connection_status);
|
|
}
|
|
|
|
if (vary_data.is_valid())
|
|
vary_data.Persist(pickle);
|
|
|
|
pickle->WriteString(remote_endpoint.ToStringWithoutPort());
|
|
pickle->WriteUInt16(remote_endpoint.port());
|
|
|
|
if (was_alpn_negotiated)
|
|
pickle->WriteString(alpn_negotiated_protocol);
|
|
|
|
if (connection_info != HttpConnectionInfo::kUNKNOWN) {
|
|
pickle->WriteInt(static_cast<int>(connection_info));
|
|
}
|
|
|
|
if (ssl_info.is_valid() && ssl_info.key_exchange_group != 0)
|
|
pickle->WriteInt(ssl_info.key_exchange_group);
|
|
|
|
if (flags & RESPONSE_INFO_HAS_STALENESS) {
|
|
pickle->WriteInt64(
|
|
(stale_revalidate_timeout - base::Time()).InMicroseconds());
|
|
}
|
|
|
|
if (ssl_info.is_valid() && ssl_info.peer_signature_algorithm != 0)
|
|
pickle->WriteInt(ssl_info.peer_signature_algorithm);
|
|
|
|
if (!dns_aliases.empty()) {
|
|
pickle->WriteInt(dns_aliases.size());
|
|
for (const auto& alias : dns_aliases)
|
|
pickle->WriteString(alias);
|
|
}
|
|
|
|
if (browser_run_id.has_value()) {
|
|
pickle->WriteInt64(browser_run_id.value());
|
|
}
|
|
}
|
|
|
|
bool HttpResponseInfo::DidUseQuic() const {
|
|
switch (connection_info) {
|
|
case HttpConnectionInfo::kUNKNOWN:
|
|
case HttpConnectionInfo::kHTTP1_1:
|
|
case HttpConnectionInfo::kDEPRECATED_SPDY2:
|
|
case HttpConnectionInfo::kDEPRECATED_SPDY3:
|
|
case HttpConnectionInfo::kHTTP2:
|
|
case HttpConnectionInfo::kDEPRECATED_HTTP2_14:
|
|
case HttpConnectionInfo::kDEPRECATED_HTTP2_15:
|
|
case HttpConnectionInfo::kHTTP0_9:
|
|
case HttpConnectionInfo::kHTTP1_0:
|
|
return false;
|
|
case HttpConnectionInfo::kQUIC_UNKNOWN_VERSION:
|
|
case HttpConnectionInfo::kQUIC_32:
|
|
case HttpConnectionInfo::kQUIC_33:
|
|
case HttpConnectionInfo::kQUIC_34:
|
|
case HttpConnectionInfo::kQUIC_35:
|
|
case HttpConnectionInfo::kQUIC_36:
|
|
case HttpConnectionInfo::kQUIC_37:
|
|
case HttpConnectionInfo::kQUIC_38:
|
|
case HttpConnectionInfo::kQUIC_39:
|
|
case HttpConnectionInfo::kQUIC_40:
|
|
case HttpConnectionInfo::kQUIC_41:
|
|
case HttpConnectionInfo::kQUIC_42:
|
|
case HttpConnectionInfo::kQUIC_43:
|
|
case HttpConnectionInfo::kQUIC_44:
|
|
case HttpConnectionInfo::kQUIC_45:
|
|
case HttpConnectionInfo::kQUIC_46:
|
|
case HttpConnectionInfo::kQUIC_47:
|
|
case HttpConnectionInfo::kQUIC_Q048:
|
|
case HttpConnectionInfo::kQUIC_T048:
|
|
case HttpConnectionInfo::kQUIC_Q049:
|
|
case HttpConnectionInfo::kQUIC_T049:
|
|
case HttpConnectionInfo::kQUIC_Q050:
|
|
case HttpConnectionInfo::kQUIC_T050:
|
|
case HttpConnectionInfo::kQUIC_Q099:
|
|
case HttpConnectionInfo::kQUIC_T099:
|
|
case HttpConnectionInfo::kQUIC_999:
|
|
case HttpConnectionInfo::kQUIC_DRAFT_25:
|
|
case HttpConnectionInfo::kQUIC_DRAFT_27:
|
|
case HttpConnectionInfo::kQUIC_DRAFT_28:
|
|
case HttpConnectionInfo::kQUIC_DRAFT_29:
|
|
case HttpConnectionInfo::kQUIC_T051:
|
|
case HttpConnectionInfo::kQUIC_RFC_V1:
|
|
case HttpConnectionInfo::kDEPRECATED_QUIC_2_DRAFT_1:
|
|
case HttpConnectionInfo::kQUIC_2_DRAFT_8:
|
|
return true;
|
|
}
|
|
}
|
|
|
|
} // namespace net
|