Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(974)

Side by Side Diff: net/quic/quic_stream_factory.cc

Issue 2097123002: QUIC - Race Cert Verification with host resolution if certs are (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Race cert verification. Created 4 years, 5 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « net/quic/quic_stream_factory.h ('k') | net/quic/quic_stream_factory_test.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "net/quic/quic_stream_factory.h" 5 #include "net/quic/quic_stream_factory.h"
6 6
7 #include <openssl/aead.h> 7 #include <openssl/aead.h>
8 8
9 #include <algorithm> 9 #include <algorithm>
10 #include <tuple> 10 #include <tuple>
(...skipping 16 matching lines...) Expand all
27 #include "crypto/openssl_util.h" 27 #include "crypto/openssl_util.h"
28 #include "net/base/ip_address.h" 28 #include "net/base/ip_address.h"
29 #include "net/base/net_errors.h" 29 #include "net/base/net_errors.h"
30 #include "net/cert/cert_verifier.h" 30 #include "net/cert/cert_verifier.h"
31 #include "net/cert/ct_verifier.h" 31 #include "net/cert/ct_verifier.h"
32 #include "net/dns/host_resolver.h" 32 #include "net/dns/host_resolver.h"
33 #include "net/dns/single_request_host_resolver.h" 33 #include "net/dns/single_request_host_resolver.h"
34 #include "net/http/bidirectional_stream_impl.h" 34 #include "net/http/bidirectional_stream_impl.h"
35 #include "net/quic/bidirectional_stream_quic_impl.h" 35 #include "net/quic/bidirectional_stream_quic_impl.h"
36 #include "net/quic/crypto/channel_id_chromium.h" 36 #include "net/quic/crypto/channel_id_chromium.h"
37 #include "net/quic/crypto/proof_verifier.h"
37 #include "net/quic/crypto/proof_verifier_chromium.h" 38 #include "net/quic/crypto/proof_verifier_chromium.h"
38 #include "net/quic/crypto/properties_based_quic_server_info.h" 39 #include "net/quic/crypto/properties_based_quic_server_info.h"
39 #include "net/quic/crypto/quic_random.h" 40 #include "net/quic/crypto/quic_random.h"
40 #include "net/quic/crypto/quic_server_info.h" 41 #include "net/quic/crypto/quic_server_info.h"
41 #include "net/quic/port_suggester.h" 42 #include "net/quic/port_suggester.h"
42 #include "net/quic/quic_chromium_alarm_factory.h" 43 #include "net/quic/quic_chromium_alarm_factory.h"
43 #include "net/quic/quic_chromium_connection_helper.h" 44 #include "net/quic/quic_chromium_connection_helper.h"
44 #include "net/quic/quic_chromium_packet_reader.h" 45 #include "net/quic/quic_chromium_packet_reader.h"
45 #include "net/quic/quic_chromium_packet_writer.h" 46 #include "net/quic/quic_chromium_packet_writer.h"
46 #include "net/quic/quic_client_promised_info.h" 47 #include "net/quic/quic_client_promised_info.h"
(...skipping 113 matching lines...) Expand 10 before | Expand all | Expand 10 after
160 QuicConfig config; 161 QuicConfig config;
161 config.SetIdleConnectionStateLifetime( 162 config.SetIdleConnectionStateLifetime(
162 QuicTime::Delta::FromSeconds(idle_connection_timeout_seconds), 163 QuicTime::Delta::FromSeconds(idle_connection_timeout_seconds),
163 QuicTime::Delta::FromSeconds(idle_connection_timeout_seconds)); 164 QuicTime::Delta::FromSeconds(idle_connection_timeout_seconds));
164 config.SetConnectionOptionsToSend(connection_options); 165 config.SetConnectionOptionsToSend(connection_options);
165 return config; 166 return config;
166 } 167 }
167 168
168 } // namespace 169 } // namespace
169 170
171 class QuicStreamFactory::CertVerifierJob {
172 public:
173 class IgnoreProofVerifierCallback : public ProofVerifierCallback {
174 public:
175 explicit IgnoreProofVerifierCallback(CertVerifierJob* job) : job_(job) {}
176
177 ~IgnoreProofVerifierCallback() override {}
178
179 void Run(bool ok,
180 const std::string& error_details,
181 std::unique_ptr<ProofVerifyDetails>* details) override {
182 LOG(ERROR) << __FUNCTION__;
183 if (job_ == nullptr)
184 return;
185 job_->verify_callback_ = nullptr;
186 job_->OnComplete();
187 }
188
189 void Cancel() { job_ = nullptr; }
190
191 private:
192 CertVerifierJob* job_;
193 };
194
195 CertVerifierJob(const QuicServerId& server_id,
196 int cert_verify_flags,
197 QuicCryptoClientConfig* crypto_config,
198 const BoundNetLog& net_log)
199 : server_id_(server_id),
200 crypto_config_(crypto_config),
201 verify_callback_(new IgnoreProofVerifierCallback(this)),
202 verify_context_(
203 new ProofVerifyContextChromium(cert_verify_flags, net_log)),
204 net_log_(net_log),
205 weak_factory_(this) {}
206
207 ~CertVerifierJob() {
208 if (verify_callback_)
209 verify_callback_->Cancel();
210 }
211
212 QuicAsyncStatus Run(const CompletionCallback& callback) {
213 QuicCryptoClientConfig::CachedState* cached =
214 crypto_config_->LookupOrCreate(server_id_);
215 LOG(ERROR) << __FUNCTION__;
216 // Pass empty chlo_hash, signature and cert_sct so that only certificate is
217 // verified.
218 QuicAsyncStatus status = crypto_config_->proof_verifier()->VerifyProof(
219 server_id_.host(), server_id_.port(), cached->server_config(),
220 QUIC_VERSION_25, /*chlo_hash=*/"", cached->certs(),
221 /*cert_sct=*/"", /*signature=*/"", verify_context_.get(),
222 &verify_error_details_, &verify_details_, verify_callback_);
223 if (status != QUIC_FAILURE)
224 callback_ = callback;
225 return status;
226 }
227
228 void OnComplete() {
229 if (!callback_.is_null())
230 callback_.Run(OK);
231 }
232
233 const QuicServerId& server_id() const { return server_id_; }
234
235 private:
236 QuicServerId server_id_;
237 QuicCryptoClientConfig* crypto_config_;
238 IgnoreProofVerifierCallback* verify_callback_;
239 std::unique_ptr<ProofVerifyContext> verify_context_;
240 std::unique_ptr<ProofVerifyDetails> verify_details_;
241 std::string verify_error_details_;
242 const BoundNetLog net_log_;
243 CompletionCallback callback_;
244 base::WeakPtrFactory<CertVerifierJob> weak_factory_;
245
246 DISALLOW_COPY_AND_ASSIGN(CertVerifierJob);
247 };
248
170 // Responsible for creating a new QUIC session to the specified server, and 249 // Responsible for creating a new QUIC session to the specified server, and
171 // for notifying any associated requests when complete. 250 // for notifying any associated requests when complete.
172 class QuicStreamFactory::Job { 251 class QuicStreamFactory::Job {
173 public: 252 public:
174 Job(QuicStreamFactory* factory, 253 Job(QuicStreamFactory* factory,
175 HostResolver* host_resolver, 254 HostResolver* host_resolver,
176 const QuicSessionKey& key, 255 const QuicSessionKey& key,
177 bool was_alternative_service_recently_broken, 256 bool was_alternative_service_recently_broken,
178 int cert_verify_flags, 257 int cert_verify_flags,
179 QuicServerInfo* server_info, 258 QuicServerInfo* server_info,
(...skipping 444 matching lines...) Expand 10 before | Expand all | Expand 10 after
624 int threshold_public_resets_post_handshake, 703 int threshold_public_resets_post_handshake,
625 int threshold_timeouts_with_open_streams, 704 int threshold_timeouts_with_open_streams,
626 int socket_receive_buffer_size, 705 int socket_receive_buffer_size,
627 bool delay_tcp_race, 706 bool delay_tcp_race,
628 int max_server_configs_stored_in_properties, 707 int max_server_configs_stored_in_properties,
629 bool close_sessions_on_ip_change, 708 bool close_sessions_on_ip_change,
630 bool disable_quic_on_timeout_with_open_streams, 709 bool disable_quic_on_timeout_with_open_streams,
631 int idle_connection_timeout_seconds, 710 int idle_connection_timeout_seconds,
632 bool migrate_sessions_on_network_change, 711 bool migrate_sessions_on_network_change,
633 bool migrate_sessions_early, 712 bool migrate_sessions_early,
713 bool race_cert_verification,
634 const QuicTagVector& connection_options, 714 const QuicTagVector& connection_options,
635 bool enable_token_binding) 715 bool enable_token_binding)
636 : require_confirmation_(true), 716 : require_confirmation_(true),
637 net_log_(net_log), 717 net_log_(net_log),
638 host_resolver_(host_resolver), 718 host_resolver_(host_resolver),
639 client_socket_factory_(client_socket_factory), 719 client_socket_factory_(client_socket_factory),
640 http_server_properties_(http_server_properties), 720 http_server_properties_(http_server_properties),
641 transport_security_state_(transport_security_state), 721 transport_security_state_(transport_security_state),
642 cert_transparency_verifier_(cert_transparency_verifier), 722 cert_transparency_verifier_(cert_transparency_verifier),
643 quic_crypto_client_stream_factory_(quic_crypto_client_stream_factory), 723 quic_crypto_client_stream_factory_(quic_crypto_client_stream_factory),
(...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after
677 delay_tcp_race_(delay_tcp_race), 757 delay_tcp_race_(delay_tcp_race),
678 yield_after_packets_(kQuicYieldAfterPacketsRead), 758 yield_after_packets_(kQuicYieldAfterPacketsRead),
679 yield_after_duration_(QuicTime::Delta::FromMilliseconds( 759 yield_after_duration_(QuicTime::Delta::FromMilliseconds(
680 kQuicYieldAfterDurationMilliseconds)), 760 kQuicYieldAfterDurationMilliseconds)),
681 close_sessions_on_ip_change_(close_sessions_on_ip_change), 761 close_sessions_on_ip_change_(close_sessions_on_ip_change),
682 migrate_sessions_on_network_change_( 762 migrate_sessions_on_network_change_(
683 migrate_sessions_on_network_change && 763 migrate_sessions_on_network_change &&
684 NetworkChangeNotifier::AreNetworkHandlesSupported()), 764 NetworkChangeNotifier::AreNetworkHandlesSupported()),
685 migrate_sessions_early_(migrate_sessions_early && 765 migrate_sessions_early_(migrate_sessions_early &&
686 migrate_sessions_on_network_change_), 766 migrate_sessions_on_network_change_),
767 race_cert_verification_(race_cert_verification),
687 port_seed_(random_generator_->RandUint64()), 768 port_seed_(random_generator_->RandUint64()),
688 check_persisted_supports_quic_(true), 769 check_persisted_supports_quic_(true),
689 has_initialized_data_(false), 770 has_initialized_data_(false),
690 num_push_streams_created_(0), 771 num_push_streams_created_(0),
691 status_(OPEN), 772 status_(OPEN),
692 task_runner_(nullptr), 773 task_runner_(nullptr),
693 weak_factory_(this) { 774 weak_factory_(this) {
694 if (disable_quic_on_timeout_with_open_streams) 775 if (disable_quic_on_timeout_with_open_streams)
695 threshold_timeouts_with_open_streams_ = 1; 776 threshold_timeouts_with_open_streams_ = 1;
696 DCHECK(transport_security_state_); 777 DCHECK(transport_security_state_);
(...skipping 44 matching lines...) Expand 10 before | Expand all | Expand 10 after
741 CloseAllSessions(ERR_ABORTED, QUIC_CONNECTION_CANCELLED); 822 CloseAllSessions(ERR_ABORTED, QUIC_CONNECTION_CANCELLED);
742 while (!all_sessions_.empty()) { 823 while (!all_sessions_.empty()) {
743 delete all_sessions_.begin()->first; 824 delete all_sessions_.begin()->first;
744 all_sessions_.erase(all_sessions_.begin()); 825 all_sessions_.erase(all_sessions_.begin());
745 } 826 }
746 while (!active_jobs_.empty()) { 827 while (!active_jobs_.empty()) {
747 const QuicServerId server_id = active_jobs_.begin()->first; 828 const QuicServerId server_id = active_jobs_.begin()->first;
748 STLDeleteElements(&(active_jobs_[server_id])); 829 STLDeleteElements(&(active_jobs_[server_id]));
749 active_jobs_.erase(server_id); 830 active_jobs_.erase(server_id);
750 } 831 }
832 while (!active_cert_verifier_jobs_.empty()) {
833 delete active_cert_verifier_jobs_.begin()->second;
834 active_cert_verifier_jobs_.erase(active_cert_verifier_jobs_.begin());
835 }
751 if (migrate_sessions_on_network_change_) { 836 if (migrate_sessions_on_network_change_) {
752 NetworkChangeNotifier::RemoveNetworkObserver(this); 837 NetworkChangeNotifier::RemoveNetworkObserver(this);
753 } else if (close_sessions_on_ip_change_) { 838 } else if (close_sessions_on_ip_change_) {
754 NetworkChangeNotifier::RemoveIPAddressObserver(this); 839 NetworkChangeNotifier::RemoveIPAddressObserver(this);
755 } 840 }
756 } 841 }
757 842
758 void QuicStreamFactory::set_require_confirmation(bool require_confirmation) { 843 void QuicStreamFactory::set_require_confirmation(bool require_confirmation) {
759 require_confirmation_ = require_confirmation; 844 require_confirmation_ = require_confirmation;
760 if (!(local_address_ == IPEndPoint())) { 845 if (!(local_address_ == IPEndPoint())) {
(...skipping 114 matching lines...) Expand 10 before | Expand all | Expand 10 after
875 if (!ContainsKey(quic_supported_servers_at_startup_, destination)) { 960 if (!ContainsKey(quic_supported_servers_at_startup_, destination)) {
876 // If there is no entry for QUIC, consider that as a new server and 961 // If there is no entry for QUIC, consider that as a new server and
877 // don't wait for Cache thread to load the data for that server. 962 // don't wait for Cache thread to load the data for that server.
878 load_from_disk_cache = false; 963 load_from_disk_cache = false;
879 } 964 }
880 if (load_from_disk_cache && CryptoConfigCacheIsEmpty(server_id)) { 965 if (load_from_disk_cache && CryptoConfigCacheIsEmpty(server_id)) {
881 quic_server_info = quic_server_info_factory_->GetForServer(server_id); 966 quic_server_info = quic_server_info_factory_->GetForServer(server_id);
882 } 967 }
883 } 968 }
884 969
970 StartCertVerifyJob(server_id, cert_verify_flags, net_log);
971
885 QuicSessionKey key(destination, server_id); 972 QuicSessionKey key(destination, server_id);
886 std::unique_ptr<Job> job( 973 std::unique_ptr<Job> job(
887 new Job(this, host_resolver_, key, WasQuicRecentlyBroken(server_id), 974 new Job(this, host_resolver_, key, WasQuicRecentlyBroken(server_id),
888 cert_verify_flags, quic_server_info, net_log)); 975 cert_verify_flags, quic_server_info, net_log));
889 int rv = job->Run(base::Bind(&QuicStreamFactory::OnJobComplete, 976 int rv = job->Run(base::Bind(&QuicStreamFactory::OnJobComplete,
890 base::Unretained(this), job.get())); 977 base::Unretained(this), job.get()));
891 if (rv == ERR_IO_PENDING) { 978 if (rv == ERR_IO_PENDING) {
892 active_requests_[request] = server_id; 979 active_requests_[request] = server_id;
893 job_requests_map_[server_id].insert(request); 980 job_requests_map_[server_id].insert(request);
894 active_jobs_[server_id].insert(job.release()); 981 active_jobs_[server_id].insert(job.release());
(...skipping 112 matching lines...) Expand 10 before | Expand all | Expand 10 after
1007 for (Job* other_job : active_jobs_[server_id]) { 1094 for (Job* other_job : active_jobs_[server_id]) {
1008 if (other_job != job) 1095 if (other_job != job)
1009 other_job->Cancel(); 1096 other_job->Cancel();
1010 } 1097 }
1011 1098
1012 STLDeleteElements(&(active_jobs_[server_id])); 1099 STLDeleteElements(&(active_jobs_[server_id]));
1013 active_jobs_.erase(server_id); 1100 active_jobs_.erase(server_id);
1014 job_requests_map_.erase(server_id); 1101 job_requests_map_.erase(server_id);
1015 } 1102 }
1016 1103
1104 void QuicStreamFactory::OnCertVerifyJobComplete(CertVerifierJob* job, int rv) {
1105 LOG(ERROR) << __FUNCTION__;
1106 active_cert_verifier_jobs_.erase(job->server_id());
1107 }
1108
1017 std::unique_ptr<QuicHttpStream> QuicStreamFactory::CreateFromSession( 1109 std::unique_ptr<QuicHttpStream> QuicStreamFactory::CreateFromSession(
1018 QuicChromiumClientSession* session) { 1110 QuicChromiumClientSession* session) {
1019 return std::unique_ptr<QuicHttpStream>( 1111 return std::unique_ptr<QuicHttpStream>(
1020 new QuicHttpStream(session->GetWeakPtr())); 1112 new QuicHttpStream(session->GetWeakPtr()));
1021 } 1113 }
1022 1114
1023 QuicChromiumClientSession::QuicDisabledReason 1115 QuicChromiumClientSession::QuicDisabledReason
1024 QuicStreamFactory::QuicDisabledReason(uint16_t port) const { 1116 QuicStreamFactory::QuicDisabledReason(uint16_t port) const {
1025 if (max_number_of_lossy_connections_ > 0 && 1117 if (max_number_of_lossy_connections_ > 0 &&
1026 number_of_lossy_connections_.find(port) != 1118 number_of_lossy_connections_.find(port) !=
(...skipping 508 matching lines...) Expand 10 before | Expand all | Expand 10 after
1535 // TODO(rtenneti): crbug.com/498823 - delete active_sessions_.empty() check. 1627 // TODO(rtenneti): crbug.com/498823 - delete active_sessions_.empty() check.
1536 if (active_sessions_.empty()) 1628 if (active_sessions_.empty())
1537 return false; 1629 return false;
1538 return ContainsKey(active_sessions_, server_id); 1630 return ContainsKey(active_sessions_, server_id);
1539 } 1631 }
1540 1632
1541 bool QuicStreamFactory::HasActiveJob(const QuicServerId& server_id) const { 1633 bool QuicStreamFactory::HasActiveJob(const QuicServerId& server_id) const {
1542 return ContainsKey(active_jobs_, server_id); 1634 return ContainsKey(active_jobs_, server_id);
1543 } 1635 }
1544 1636
1637 bool QuicStreamFactory::HasActiveCertVerifierJob(
1638 const QuicServerId& server_id) const {
1639 return ContainsKey(active_cert_verifier_jobs_, server_id);
1640 }
1641
1545 int QuicStreamFactory::ConfigureSocket(DatagramClientSocket* socket, 1642 int QuicStreamFactory::ConfigureSocket(DatagramClientSocket* socket,
1546 IPEndPoint addr, 1643 IPEndPoint addr,
1547 NetworkHandle network) { 1644 NetworkHandle network) {
1548 if (enable_non_blocking_io_ && 1645 if (enable_non_blocking_io_ &&
1549 client_socket_factory_ == ClientSocketFactory::GetDefaultFactory()) { 1646 client_socket_factory_ == ClientSocketFactory::GetDefaultFactory()) {
1550 #if defined(OS_WIN) 1647 #if defined(OS_WIN)
1551 static_cast<UDPClientSocket*>(socket)->UseNonBlockingIO(); 1648 static_cast<UDPClientSocket*>(socket)->UseNonBlockingIO();
1552 #endif 1649 #endif
1553 } 1650 }
1554 1651
(...skipping 187 matching lines...) Expand 10 before | Expand all | Expand 10 after
1742 alternative_service); 1839 alternative_service);
1743 } 1840 }
1744 1841
1745 bool QuicStreamFactory::CryptoConfigCacheIsEmpty( 1842 bool QuicStreamFactory::CryptoConfigCacheIsEmpty(
1746 const QuicServerId& server_id) { 1843 const QuicServerId& server_id) {
1747 QuicCryptoClientConfig::CachedState* cached = 1844 QuicCryptoClientConfig::CachedState* cached =
1748 crypto_config_.LookupOrCreate(server_id); 1845 crypto_config_.LookupOrCreate(server_id);
1749 return cached->IsEmpty(); 1846 return cached->IsEmpty();
1750 } 1847 }
1751 1848
1849 void QuicStreamFactory::StartCertVerifyJob(const QuicServerId& server_id,
1850 int cert_verify_flags,
1851 const BoundNetLog& net_log) {
1852 LOG(ERROR) << __FUNCTION__ << " " << race_cert_verification_;
1853 if (!race_cert_verification_)
1854 return;
1855 QuicCryptoClientConfig::CachedState* cached =
1856 crypto_config_.LookupOrCreate(server_id);
1857 if (!cached || cached->certs().empty() || cached->proof_valid() ||
1858 HasActiveCertVerifierJob(server_id)) {
1859 LOG(ERROR) << __FUNCTION__ << " " << __LINE__;
1860 return;
1861 }
1862 std::unique_ptr<CertVerifierJob> cert_verifier_job(new CertVerifierJob(
1863 server_id, cert_verify_flags, &crypto_config_, net_log));
1864 QuicAsyncStatus status = cert_verifier_job->Run(
1865 base::Bind(&QuicStreamFactory::OnCertVerifyJobComplete,
1866 base::Unretained(this), cert_verifier_job.get()));
1867 if (status != QUIC_FAILURE)
1868 active_cert_verifier_jobs_[server_id] = cert_verifier_job.release();
1869 }
1870
1752 void QuicStreamFactory::InitializeCachedStateInCryptoConfig( 1871 void QuicStreamFactory::InitializeCachedStateInCryptoConfig(
1753 const QuicServerId& server_id, 1872 const QuicServerId& server_id,
1754 const std::unique_ptr<QuicServerInfo>& server_info, 1873 const std::unique_ptr<QuicServerInfo>& server_info,
1755 QuicConnectionId* connection_id) { 1874 QuicConnectionId* connection_id) {
1756 QuicCryptoClientConfig::CachedState* cached = 1875 QuicCryptoClientConfig::CachedState* cached =
1757 crypto_config_.LookupOrCreate(server_id); 1876 crypto_config_.LookupOrCreate(server_id);
1758 if (cached->has_server_designated_connection_id()) 1877 if (cached->has_server_designated_connection_id())
1759 *connection_id = cached->GetNextServerDesignatedConnectionId(); 1878 *connection_id = cached->GetNextServerDesignatedConnectionId();
1760 1879
1761 if (!cached->IsEmpty()) 1880 if (!cached->IsEmpty())
(...skipping 101 matching lines...) Expand 10 before | Expand all | Expand 10 after
1863 // Since the session was active, there's no longer an 1982 // Since the session was active, there's no longer an
1864 // HttpStreamFactoryImpl::Job running which can mark it broken, unless the TCP 1983 // HttpStreamFactoryImpl::Job running which can mark it broken, unless the TCP
1865 // job also fails. So to avoid not using QUIC when we otherwise could, we mark 1984 // job also fails. So to avoid not using QUIC when we otherwise could, we mark
1866 // it as recently broken, which means that 0-RTT will be disabled but we'll 1985 // it as recently broken, which means that 0-RTT will be disabled but we'll
1867 // still race. 1986 // still race.
1868 http_server_properties_->MarkAlternativeServiceRecentlyBroken( 1987 http_server_properties_->MarkAlternativeServiceRecentlyBroken(
1869 alternative_service); 1988 alternative_service);
1870 } 1989 }
1871 1990
1872 } // namespace net 1991 } // namespace net
OLDNEW
« no previous file with comments | « net/quic/quic_stream_factory.h ('k') | net/quic/quic_stream_factory_test.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698