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
3 // found in the LICENSE file.
5 #include "net/quic/quic_stream_factory.h"
10 #include "base/message_loop/message_loop.h"
11 #include "base/message_loop/message_loop_proxy.h"
12 #include "base/metrics/field_trial.h"
13 #include "base/metrics/histogram.h"
14 #include "base/profiler/scoped_tracker.h"
15 #include "base/rand_util.h"
16 #include "base/stl_util.h"
17 #include "base/strings/string_util.h"
18 #include "base/values.h"
19 #include "net/base/net_errors.h"
20 #include "net/cert/cert_verifier.h"
21 #include "net/dns/host_resolver.h"
22 #include "net/dns/single_request_host_resolver.h"
23 #include "net/http/http_server_properties.h"
24 #include "net/quic/crypto/channel_id_chromium.h"
25 #include "net/quic/crypto/proof_verifier_chromium.h"
26 #include "net/quic/crypto/quic_random.h"
27 #include "net/quic/crypto/quic_server_info.h"
28 #include "net/quic/port_suggester.h"
29 #include "net/quic/quic_client_session.h"
30 #include "net/quic/quic_clock.h"
31 #include "net/quic/quic_connection.h"
32 #include "net/quic/quic_connection_helper.h"
33 #include "net/quic/quic_crypto_client_stream_factory.h"
34 #include "net/quic/quic_default_packet_writer.h"
35 #include "net/quic/quic_flags.h"
36 #include "net/quic/quic_http_stream.h"
37 #include "net/quic/quic_protocol.h"
38 #include "net/quic/quic_server_id.h"
39 #include "net/socket/client_socket_factory.h"
40 #include "net/udp/udp_client_socket.h"
43 #include "base/win/windows_version.h"
50 enum CreateSessionFailure
{
51 CREATION_ERROR_CONNECTING_SOCKET
,
52 CREATION_ERROR_SETTING_RECEIVE_BUFFER
,
53 CREATION_ERROR_SETTING_SEND_BUFFER
,
57 // When a connection is idle for 30 seconds it will be closed.
58 const int kIdleConnectionTimeoutSeconds
= 30;
60 // The initial receive window size for both streams and sessions.
61 const int32 kInitialReceiveWindowSize
= 10 * 1024 * 1024; // 10MB
63 // Set the maximum number of undecryptable packets the connection will store.
64 const int32 kMaxUndecryptablePackets
= 100;
66 void HistogramCreateSessionFailure(enum CreateSessionFailure error
) {
67 UMA_HISTOGRAM_ENUMERATION("Net.QuicSession.CreationError", error
,
71 bool IsEcdsaSupported() {
73 if (base::win::GetVersion() < base::win::VERSION_VISTA
)
80 QuicConfig
InitializeQuicConfig(const QuicTagVector
& connection_options
) {
82 config
.SetIdleConnectionStateLifetime(
83 QuicTime::Delta::FromSeconds(kIdleConnectionTimeoutSeconds
),
84 QuicTime::Delta::FromSeconds(kIdleConnectionTimeoutSeconds
));
85 config
.SetConnectionOptionsToSend(connection_options
);
89 class DefaultPacketWriterFactory
: public QuicConnection::PacketWriterFactory
{
91 explicit DefaultPacketWriterFactory(DatagramClientSocket
* socket
)
93 ~DefaultPacketWriterFactory() override
{}
95 QuicPacketWriter
* Create(QuicConnection
* connection
) const override
;
98 DatagramClientSocket
* socket_
;
101 QuicPacketWriter
* DefaultPacketWriterFactory::Create(
102 QuicConnection
* connection
) const {
103 scoped_ptr
<QuicDefaultPacketWriter
> writer(
104 new QuicDefaultPacketWriter(socket_
));
105 writer
->SetConnection(connection
);
106 return writer
.release();
111 QuicStreamFactory::IpAliasKey::IpAliasKey() {}
113 QuicStreamFactory::IpAliasKey::IpAliasKey(IPEndPoint ip_endpoint
,
115 : ip_endpoint(ip_endpoint
),
116 is_https(is_https
) {}
118 QuicStreamFactory::IpAliasKey::~IpAliasKey() {}
120 bool QuicStreamFactory::IpAliasKey::operator<(
121 const QuicStreamFactory::IpAliasKey
& other
) const {
122 if (!(ip_endpoint
== other
.ip_endpoint
)) {
123 return ip_endpoint
< other
.ip_endpoint
;
125 return is_https
< other
.is_https
;
128 bool QuicStreamFactory::IpAliasKey::operator==(
129 const QuicStreamFactory::IpAliasKey
& other
) const {
130 return is_https
== other
.is_https
&&
131 ip_endpoint
== other
.ip_endpoint
;
134 // Responsible for creating a new QUIC session to the specified server, and
135 // for notifying any associated requests when complete.
136 class QuicStreamFactory::Job
{
138 Job(QuicStreamFactory
* factory
,
139 HostResolver
* host_resolver
,
140 const HostPortPair
& host_port_pair
,
142 bool was_alternate_protocol_recently_broken
,
143 PrivacyMode privacy_mode
,
145 QuicServerInfo
* server_info
,
146 const BoundNetLog
& net_log
);
148 // Creates a new job to handle the resumption of for connecting an
150 Job(QuicStreamFactory
* factory
,
151 HostResolver
* host_resolver
,
152 QuicClientSession
* session
,
153 QuicServerId server_id
);
157 int Run(const CompletionCallback
& callback
);
161 int DoResolveHostComplete(int rv
);
162 int DoLoadServerInfo();
163 int DoLoadServerInfoComplete(int rv
);
165 int DoResumeConnect();
166 int DoConnectComplete(int rv
);
168 void OnIOComplete(int rv
);
170 void RunAuxilaryJob();
174 void CancelWaitForDataReadyCallback();
176 const QuicServerId
server_id() const { return server_id_
; }
178 base::WeakPtr
<Job
> GetWeakPtr() { return weak_factory_
.GetWeakPtr(); }
184 STATE_RESOLVE_HOST_COMPLETE
,
185 STATE_LOAD_SERVER_INFO
,
186 STATE_LOAD_SERVER_INFO_COMPLETE
,
188 STATE_RESUME_CONNECT
,
189 STATE_CONNECT_COMPLETE
,
193 QuicStreamFactory
* factory_
;
194 SingleRequestHostResolver host_resolver_
;
195 QuicServerId server_id_
;
197 bool was_alternate_protocol_recently_broken_
;
198 scoped_ptr
<QuicServerInfo
> server_info_
;
199 bool started_another_job_
;
200 const BoundNetLog net_log_
;
201 QuicClientSession
* session_
;
202 CompletionCallback callback_
;
203 AddressList address_list_
;
204 base::TimeTicks dns_resolution_start_time_
;
205 base::TimeTicks dns_resolution_end_time_
;
206 base::WeakPtrFactory
<Job
> weak_factory_
;
207 DISALLOW_COPY_AND_ASSIGN(Job
);
210 QuicStreamFactory::Job::Job(QuicStreamFactory
* factory
,
211 HostResolver
* host_resolver
,
212 const HostPortPair
& host_port_pair
,
214 bool was_alternate_protocol_recently_broken
,
215 PrivacyMode privacy_mode
,
217 QuicServerInfo
* server_info
,
218 const BoundNetLog
& net_log
)
219 : io_state_(STATE_RESOLVE_HOST
),
221 host_resolver_(host_resolver
),
222 server_id_(host_port_pair
, is_https
, privacy_mode
),
224 was_alternate_protocol_recently_broken_(
225 was_alternate_protocol_recently_broken
),
226 server_info_(server_info
),
227 started_another_job_(false),
230 weak_factory_(this) {
233 QuicStreamFactory::Job::Job(QuicStreamFactory
* factory
,
234 HostResolver
* host_resolver
,
235 QuicClientSession
* session
,
236 QuicServerId server_id
)
237 : io_state_(STATE_RESUME_CONNECT
),
239 host_resolver_(host_resolver
), // unused
240 server_id_(server_id
),
241 is_post_(false), // unused
242 was_alternate_protocol_recently_broken_(false), // unused
243 started_another_job_(false), // unused
244 net_log_(session
->net_log()), // unused
246 weak_factory_(this) {
249 QuicStreamFactory::Job::~Job() {
250 // If disk cache has a pending WaitForDataReadyCallback, cancel that callback.
252 server_info_
->ResetWaitForDataReadyCallback();
255 int QuicStreamFactory::Job::Run(const CompletionCallback
& callback
) {
257 if (rv
== ERR_IO_PENDING
)
258 callback_
= callback
;
260 return rv
> 0 ? OK
: rv
;
263 int QuicStreamFactory::Job::DoLoop(int rv
) {
265 IoState state
= io_state_
;
266 io_state_
= STATE_NONE
;
268 case STATE_RESOLVE_HOST
:
270 rv
= DoResolveHost();
272 case STATE_RESOLVE_HOST_COMPLETE
:
273 rv
= DoResolveHostComplete(rv
);
275 case STATE_LOAD_SERVER_INFO
:
277 rv
= DoLoadServerInfo();
279 case STATE_LOAD_SERVER_INFO_COMPLETE
:
280 rv
= DoLoadServerInfoComplete(rv
);
286 case STATE_RESUME_CONNECT
:
288 rv
= DoResumeConnect();
290 case STATE_CONNECT_COMPLETE
:
291 rv
= DoConnectComplete(rv
);
294 NOTREACHED() << "io_state_: " << io_state_
;
297 } while (io_state_
!= STATE_NONE
&& rv
!= ERR_IO_PENDING
);
301 void QuicStreamFactory::Job::OnIOComplete(int rv
) {
302 // TODO(vadimt): Remove ScopedTracker below once crbug.com/422516 is fixed.
303 tracked_objects::ScopedTracker
tracking_profile1(
304 FROM_HERE_WITH_EXPLICIT_FUNCTION(
305 "422516 QuicStreamFactory::Job::OnIOComplete1"));
309 tracked_objects::ScopedTracker
tracking_profile2(
310 FROM_HERE_WITH_EXPLICIT_FUNCTION(
311 "422516 QuicStreamFactory::Job::OnIOComplete2"));
313 if (rv
!= ERR_IO_PENDING
&& !callback_
.is_null()) {
318 void QuicStreamFactory::Job::RunAuxilaryJob() {
319 int rv
= Run(base::Bind(&QuicStreamFactory::OnJobComplete
,
320 base::Unretained(factory_
), this));
321 if (rv
!= ERR_IO_PENDING
)
322 factory_
->OnJobComplete(this, rv
);
325 void QuicStreamFactory::Job::Cancel() {
328 session_
->connection()->SendConnectionClose(QUIC_CONNECTION_CANCELLED
);
331 void QuicStreamFactory::Job::CancelWaitForDataReadyCallback() {
332 // If we are waiting for WaitForDataReadyCallback, then cancel the callback.
333 if (io_state_
!= STATE_LOAD_SERVER_INFO_COMPLETE
)
335 server_info_
->CancelWaitForDataReadyCallback();
339 int QuicStreamFactory::Job::DoResolveHost() {
340 // TODO(vadimt): Remove ScopedTracker below once crbug.com/422516 is fixed.
341 tracked_objects::ScopedTracker
tracking_profile(
342 FROM_HERE_WITH_EXPLICIT_FUNCTION(
343 "422516 QuicStreamFactory::Job::DoResolveHost"));
345 // Start loading the data now, and wait for it after we resolve the host.
347 server_info_
->Start();
350 io_state_
= STATE_RESOLVE_HOST_COMPLETE
;
351 dns_resolution_start_time_
= base::TimeTicks::Now();
352 return host_resolver_
.Resolve(
353 HostResolver::RequestInfo(server_id_
.host_port_pair()), DEFAULT_PRIORITY
,
355 base::Bind(&QuicStreamFactory::Job::OnIOComplete
, GetWeakPtr()),
359 int QuicStreamFactory::Job::DoResolveHostComplete(int rv
) {
360 // TODO(vadimt): Remove ScopedTracker below once crbug.com/422516 is fixed.
361 tracked_objects::ScopedTracker
tracking_profile(
362 FROM_HERE_WITH_EXPLICIT_FUNCTION(
363 "422516 QuicStreamFactory::Job::DoResolveHostComplete"));
365 dns_resolution_end_time_
= base::TimeTicks::Now();
366 UMA_HISTOGRAM_TIMES("Net.QuicSession.HostResolutionTime",
367 dns_resolution_end_time_
- dns_resolution_start_time_
);
371 DCHECK(!factory_
->HasActiveSession(server_id_
));
373 // Inform the factory of this resolution, which will set up
374 // a session alias, if possible.
375 if (factory_
->OnResolution(server_id_
, address_list_
)) {
380 io_state_
= STATE_LOAD_SERVER_INFO
;
382 io_state_
= STATE_CONNECT
;
386 int QuicStreamFactory::Job::DoLoadServerInfo() {
387 // TODO(vadimt): Remove ScopedTracker below once crbug.com/422516 is fixed.
388 tracked_objects::ScopedTracker
tracking_profile(
389 FROM_HERE_WITH_EXPLICIT_FUNCTION(
390 "422516 QuicStreamFactory::Job::DoLoadServerInfo"));
392 io_state_
= STATE_LOAD_SERVER_INFO_COMPLETE
;
394 DCHECK(server_info_
);
396 // To mitigate the effects of disk cache taking too long to load QUIC server
397 // information, set up a timer to cancel WaitForDataReady's callback.
398 if (factory_
->load_server_info_timeout_srtt_multiplier_
> 0) {
399 int64 load_server_info_timeout_ms
=
400 (factory_
->load_server_info_timeout_srtt_multiplier_
*
401 factory_
->GetServerNetworkStatsSmoothedRttInMicroseconds(server_id_
)) /
403 if (load_server_info_timeout_ms
> 0) {
404 factory_
->task_runner_
->PostDelayedTask(
406 base::Bind(&QuicStreamFactory::Job::CancelWaitForDataReadyCallback
,
408 base::TimeDelta::FromMilliseconds(load_server_info_timeout_ms
));
412 int rv
= server_info_
->WaitForDataReady(
413 base::Bind(&QuicStreamFactory::Job::OnIOComplete
, GetWeakPtr()));
414 if (rv
== ERR_IO_PENDING
&& factory_
->enable_connection_racing()) {
415 // If we are waiting to load server config from the disk cache, then start
417 started_another_job_
= true;
418 factory_
->CreateAuxilaryJob(server_id_
, is_post_
, net_log_
);
423 int QuicStreamFactory::Job::DoLoadServerInfoComplete(int rv
) {
424 // TODO(vadimt): Remove ScopedTracker below once crbug.com/422516 is fixed.
425 tracked_objects::ScopedTracker
tracking_profile(
426 FROM_HERE_WITH_EXPLICIT_FUNCTION(
427 "422516 QuicStreamFactory::Job::DoLoadServerInfoComplete"));
429 UMA_HISTOGRAM_TIMES("Net.QuicServerInfo.DiskCacheWaitForDataReadyTime",
430 base::TimeTicks::Now() - dns_resolution_end_time_
);
433 server_info_
.reset();
435 if (started_another_job_
&&
436 (!server_info_
|| server_info_
->state().server_config
.empty() ||
437 !factory_
->CryptoConfigCacheIsEmpty(server_id_
))) {
438 // If we have started another job and if we didn't load the server config
439 // from the disk cache or if we have received a new server config from the
440 // server, then cancel the current job.
441 io_state_
= STATE_NONE
;
442 return ERR_CONNECTION_CLOSED
;
445 io_state_
= STATE_CONNECT
;
449 int QuicStreamFactory::Job::DoConnect() {
450 // TODO(vadimt): Remove ScopedTracker below once crbug.com/422516 is fixed.
451 tracked_objects::ScopedTracker
tracking_profile(
452 FROM_HERE_WITH_EXPLICIT_FUNCTION(
453 "422516 QuicStreamFactory::Job::DoConnect"));
455 io_state_
= STATE_CONNECT_COMPLETE
;
458 factory_
->CreateSession(server_id_
, server_info_
.Pass(), address_list_
,
459 dns_resolution_end_time_
, net_log_
, &session_
);
461 DCHECK(rv
!= ERR_IO_PENDING
);
466 if (!session_
->connection()->connected()) {
467 return ERR_CONNECTION_CLOSED
;
470 // TODO(vadimt): Remove ScopedTracker below once crbug.com/422516 is fixed.
471 tracked_objects::ScopedTracker
tracking_profile1(
472 FROM_HERE_WITH_EXPLICIT_FUNCTION(
473 "422516 QuicStreamFactory::Job::DoConnect1"));
475 session_
->StartReading();
476 if (!session_
->connection()->connected()) {
477 return ERR_QUIC_PROTOCOL_ERROR
;
479 bool require_confirmation
=
480 factory_
->require_confirmation() || is_post_
||
481 was_alternate_protocol_recently_broken_
;
483 // TODO(vadimt): Remove ScopedTracker below once crbug.com/422516 is fixed.
484 tracked_objects::ScopedTracker
tracking_profile2(
485 FROM_HERE_WITH_EXPLICIT_FUNCTION(
486 "422516 QuicStreamFactory::Job::DoConnect2"));
488 rv
= session_
->CryptoConnect(
489 require_confirmation
,
490 base::Bind(&QuicStreamFactory::Job::OnIOComplete
, GetWeakPtr()));
494 int QuicStreamFactory::Job::DoResumeConnect() {
495 // TODO(vadimt): Remove ScopedTracker below once crbug.com/422516 is fixed.
496 tracked_objects::ScopedTracker
tracking_profile(
497 FROM_HERE_WITH_EXPLICIT_FUNCTION(
498 "422516 QuicStreamFactory::Job::DoResumeConnect"));
500 io_state_
= STATE_CONNECT_COMPLETE
;
502 int rv
= session_
->ResumeCryptoConnect(
503 base::Bind(&QuicStreamFactory::Job::OnIOComplete
, GetWeakPtr()));
508 int QuicStreamFactory::Job::DoConnectComplete(int rv
) {
509 // TODO(vadimt): Remove ScopedTracker below once crbug.com/422516 is fixed.
510 tracked_objects::ScopedTracker
tracking_profile(
511 FROM_HERE_WITH_EXPLICIT_FUNCTION(
512 "422516 QuicStreamFactory::Job::DoConnectComplete"));
517 DCHECK(!factory_
->HasActiveSession(server_id_
));
518 // There may well now be an active session for this IP. If so, use the
519 // existing session instead.
520 AddressList
address(session_
->connection()->peer_address());
521 if (factory_
->OnResolution(server_id_
, address
)) {
522 session_
->connection()->SendConnectionClose(QUIC_CONNECTION_IP_POOLED
);
527 factory_
->ActivateSession(server_id_
, session_
);
532 QuicStreamRequest::QuicStreamRequest(QuicStreamFactory
* factory
)
533 : factory_(factory
) {}
535 QuicStreamRequest::~QuicStreamRequest() {
536 if (factory_
&& !callback_
.is_null())
537 factory_
->CancelRequest(this);
540 int QuicStreamRequest::Request(const HostPortPair
& host_port_pair
,
542 PrivacyMode privacy_mode
,
543 base::StringPiece method
,
544 const BoundNetLog
& net_log
,
545 const CompletionCallback
& callback
) {
547 DCHECK(callback_
.is_null());
549 int rv
= factory_
->Create(host_port_pair
, is_https
, privacy_mode
, method
,
551 if (rv
== ERR_IO_PENDING
) {
552 host_port_pair_
= host_port_pair
;
553 is_https_
= is_https
;
555 callback_
= callback
;
564 void QuicStreamRequest::set_stream(scoped_ptr
<QuicHttpStream
> stream
) {
566 stream_
= stream
.Pass();
569 void QuicStreamRequest::OnRequestComplete(int rv
) {
574 scoped_ptr
<QuicHttpStream
> QuicStreamRequest::ReleaseStream() {
576 return stream_
.Pass();
579 QuicStreamFactory::QuicStreamFactory(
580 HostResolver
* host_resolver
,
581 ClientSocketFactory
* client_socket_factory
,
582 base::WeakPtr
<HttpServerProperties
> http_server_properties
,
583 CertVerifier
* cert_verifier
,
584 ChannelIDService
* channel_id_service
,
585 TransportSecurityState
* transport_security_state
,
586 QuicCryptoClientStreamFactory
* quic_crypto_client_stream_factory
,
587 QuicRandom
* random_generator
,
589 size_t max_packet_length
,
590 const std::string
& user_agent_id
,
591 const QuicVersionVector
& supported_versions
,
592 bool enable_port_selection
,
593 bool always_require_handshake_confirmation
,
594 bool disable_connection_pooling
,
595 float load_server_info_timeout_srtt_multiplier
,
596 bool enable_connection_racing
,
597 bool enable_non_blocking_io
,
598 bool disable_disk_cache
,
599 int socket_receive_buffer_size
,
600 const QuicTagVector
& connection_options
)
601 : require_confirmation_(true),
602 host_resolver_(host_resolver
),
603 client_socket_factory_(client_socket_factory
),
604 http_server_properties_(http_server_properties
),
605 transport_security_state_(transport_security_state
),
606 quic_server_info_factory_(nullptr),
607 quic_crypto_client_stream_factory_(quic_crypto_client_stream_factory
),
608 random_generator_(random_generator
),
610 max_packet_length_(max_packet_length
),
611 config_(InitializeQuicConfig(connection_options
)),
612 supported_versions_(supported_versions
),
613 enable_port_selection_(enable_port_selection
),
614 always_require_handshake_confirmation_(
615 always_require_handshake_confirmation
),
616 disable_connection_pooling_(disable_connection_pooling
),
617 load_server_info_timeout_srtt_multiplier_(
618 load_server_info_timeout_srtt_multiplier
),
619 enable_connection_racing_(enable_connection_racing
),
620 enable_non_blocking_io_(enable_non_blocking_io
),
621 disable_disk_cache_(disable_disk_cache
),
622 socket_receive_buffer_size_(socket_receive_buffer_size
),
623 port_seed_(random_generator_
->RandUint64()),
624 check_persisted_supports_quic_(true),
625 task_runner_(nullptr),
626 weak_factory_(this) {
627 DCHECK(transport_security_state_
);
628 crypto_config_
.set_user_agent_id(user_agent_id
);
629 crypto_config_
.AddCanonicalSuffix(".c.youtube.com");
630 crypto_config_
.AddCanonicalSuffix(".googlevideo.com");
631 crypto_config_
.SetProofVerifier(
632 new ProofVerifierChromium(cert_verifier
, transport_security_state
));
633 crypto_config_
.SetChannelIDSource(
634 new ChannelIDSourceChromium(channel_id_service
));
636 if (cpu
.has_aesni() && cpu
.has_avx())
637 crypto_config_
.PreferAesGcm();
638 if (!IsEcdsaSupported())
639 crypto_config_
.DisableEcdsa();
642 QuicStreamFactory::~QuicStreamFactory() {
643 CloseAllSessions(ERR_ABORTED
);
644 while (!all_sessions_
.empty()) {
645 delete all_sessions_
.begin()->first
;
646 all_sessions_
.erase(all_sessions_
.begin());
648 while (!active_jobs_
.empty()) {
649 const QuicServerId server_id
= active_jobs_
.begin()->first
;
650 STLDeleteElements(&(active_jobs_
[server_id
]));
651 active_jobs_
.erase(server_id
);
655 void QuicStreamFactory::set_require_confirmation(bool require_confirmation
) {
656 require_confirmation_
= require_confirmation
;
657 if (http_server_properties_
&& (!(local_address_
== IPEndPoint()))) {
658 http_server_properties_
->SetSupportsQuic(!require_confirmation
,
659 local_address_
.address());
663 int QuicStreamFactory::Create(const HostPortPair
& host_port_pair
,
665 PrivacyMode privacy_mode
,
666 base::StringPiece method
,
667 const BoundNetLog
& net_log
,
668 QuicStreamRequest
* request
) {
669 QuicServerId
server_id(host_port_pair
, is_https
, privacy_mode
);
670 if (HasActiveSession(server_id
)) {
671 request
->set_stream(CreateIfSessionExists(server_id
, net_log
));
675 if (HasActiveJob(server_id
)) {
676 active_requests_
[request
] = server_id
;
677 job_requests_map_
[server_id
].insert(request
);
678 return ERR_IO_PENDING
;
681 // TODO(rtenneti): |task_runner_| is used by the Job. Initialize task_runner_
682 // in the constructor after WebRequestActionWithThreadsTest.* tests are fixed.
684 task_runner_
= base::MessageLoop::current()->message_loop_proxy().get();
686 QuicServerInfo
* quic_server_info
= nullptr;
687 if (quic_server_info_factory_
) {
688 bool load_from_disk_cache
= !disable_disk_cache_
;
689 if (http_server_properties_
) {
690 const AlternateProtocolMap
& alternate_protocol_map
=
691 http_server_properties_
->alternate_protocol_map();
692 AlternateProtocolMap::const_iterator it
=
693 alternate_protocol_map
.Peek(server_id
.host_port_pair());
694 if (it
== alternate_protocol_map
.end() || it
->second
.protocol
!= QUIC
) {
695 // If there is no entry for QUIC, consider that as a new server and
696 // don't wait for Cache thread to load the data for that server.
697 load_from_disk_cache
= false;
700 if (load_from_disk_cache
&& CryptoConfigCacheIsEmpty(server_id
)) {
701 quic_server_info
= quic_server_info_factory_
->GetForServer(server_id
);
705 scoped_ptr
<Job
> job(new Job(this, host_resolver_
, host_port_pair
, is_https
,
706 WasAlternateProtocolRecentlyBroken(server_id
),
707 privacy_mode
, method
== "POST" /* is_post */,
708 quic_server_info
, net_log
));
709 int rv
= job
->Run(base::Bind(&QuicStreamFactory::OnJobComplete
,
710 base::Unretained(this), job
.get()));
711 if (rv
== ERR_IO_PENDING
) {
712 active_requests_
[request
] = server_id
;
713 job_requests_map_
[server_id
].insert(request
);
714 active_jobs_
[server_id
].insert(job
.release());
718 DCHECK(HasActiveSession(server_id
));
719 request
->set_stream(CreateIfSessionExists(server_id
, net_log
));
724 void QuicStreamFactory::CreateAuxilaryJob(const QuicServerId server_id
,
726 const BoundNetLog
& net_log
) {
727 Job
* aux_job
= new Job(this, host_resolver_
, server_id
.host_port_pair(),
728 server_id
.is_https(),
729 WasAlternateProtocolRecentlyBroken(server_id
),
730 server_id
.privacy_mode(), is_post
, nullptr, net_log
);
731 active_jobs_
[server_id
].insert(aux_job
);
732 task_runner_
->PostTask(FROM_HERE
,
733 base::Bind(&QuicStreamFactory::Job::RunAuxilaryJob
,
734 aux_job
->GetWeakPtr()));
737 bool QuicStreamFactory::OnResolution(
738 const QuicServerId
& server_id
,
739 const AddressList
& address_list
) {
740 DCHECK(!HasActiveSession(server_id
));
741 if (disable_connection_pooling_
) {
744 for (const IPEndPoint
& address
: address_list
) {
745 const IpAliasKey
ip_alias_key(address
, server_id
.is_https());
746 if (!ContainsKey(ip_aliases_
, ip_alias_key
))
749 const SessionSet
& sessions
= ip_aliases_
[ip_alias_key
];
750 for (QuicClientSession
* session
: sessions
) {
751 if (!session
->CanPool(server_id
.host(), server_id
.privacy_mode()))
753 active_sessions_
[server_id
] = session
;
754 session_aliases_
[session
].insert(server_id
);
761 void QuicStreamFactory::OnJobComplete(Job
* job
, int rv
) {
762 QuicServerId server_id
= job
->server_id();
764 JobSet
* jobs
= &(active_jobs_
[server_id
]);
765 if (jobs
->size() > 1) {
766 // If there is another pending job, then we can delete this job and let
767 // the other job handle the request.
776 // TODO(vadimt): Remove ScopedTracker below once crbug.com/422516 is fixed.
777 tracked_objects::ScopedTracker
tracking_profile1(
778 FROM_HERE_WITH_EXPLICIT_FUNCTION(
779 "422516 QuicStreamFactory::OnJobComplete1"));
781 if (!always_require_handshake_confirmation_
)
782 set_require_confirmation(false);
784 // Create all the streams, but do not notify them yet.
785 for (QuicStreamRequest
* request
: job_requests_map_
[server_id
]) {
786 DCHECK(HasActiveSession(server_id
));
787 request
->set_stream(CreateIfSessionExists(server_id
, request
->net_log()));
791 // TODO(vadimt): Remove ScopedTracker below once crbug.com/422516 is fixed.
792 tracked_objects::ScopedTracker
tracking_profile2(
793 FROM_HERE_WITH_EXPLICIT_FUNCTION(
794 "422516 QuicStreamFactory::OnJobComplete2"));
796 while (!job_requests_map_
[server_id
].empty()) {
797 RequestSet::iterator it
= job_requests_map_
[server_id
].begin();
798 QuicStreamRequest
* request
= *it
;
799 job_requests_map_
[server_id
].erase(it
);
800 active_requests_
.erase(request
);
801 // Even though we're invoking callbacks here, we don't need to worry
802 // about |this| being deleted, because the factory is owned by the
803 // profile which can not be deleted via callbacks.
804 request
->OnRequestComplete(rv
);
807 // TODO(vadimt): Remove ScopedTracker below once crbug.com/422516 is fixed.
808 tracked_objects::ScopedTracker
tracking_profile3(
809 FROM_HERE_WITH_EXPLICIT_FUNCTION(
810 "422516 QuicStreamFactory::OnJobComplete3"));
812 for (Job
* other_job
: active_jobs_
[server_id
]) {
813 if (other_job
!= job
)
817 STLDeleteElements(&(active_jobs_
[server_id
]));
818 active_jobs_
.erase(server_id
);
819 job_requests_map_
.erase(server_id
);
822 // Returns a newly created QuicHttpStream owned by the caller, if a
823 // matching session already exists. Returns nullptr otherwise.
824 scoped_ptr
<QuicHttpStream
> QuicStreamFactory::CreateIfSessionExists(
825 const QuicServerId
& server_id
,
826 const BoundNetLog
& net_log
) {
827 if (!HasActiveSession(server_id
)) {
828 DVLOG(1) << "No active session";
829 return scoped_ptr
<QuicHttpStream
>();
832 QuicClientSession
* session
= active_sessions_
[server_id
];
834 return scoped_ptr
<QuicHttpStream
>(
835 new QuicHttpStream(session
->GetWeakPtr()));
838 void QuicStreamFactory::OnIdleSession(QuicClientSession
* session
) {
841 void QuicStreamFactory::OnSessionGoingAway(QuicClientSession
* session
) {
842 const AliasSet
& aliases
= session_aliases_
[session
];
843 for (AliasSet::const_iterator it
= aliases
.begin(); it
!= aliases
.end();
845 DCHECK(active_sessions_
.count(*it
));
846 DCHECK_EQ(session
, active_sessions_
[*it
]);
847 // Track sessions which have recently gone away so that we can disable
849 if (session
->goaway_received()) {
850 gone_away_aliases_
.insert(*it
);
853 active_sessions_
.erase(*it
);
854 ProcessGoingAwaySession(session
, *it
, true);
856 ProcessGoingAwaySession(session
, all_sessions_
[session
], false);
857 if (!aliases
.empty()) {
858 const IpAliasKey
ip_alias_key(session
->connection()->peer_address(),
859 aliases
.begin()->is_https());
860 ip_aliases_
[ip_alias_key
].erase(session
);
861 if (ip_aliases_
[ip_alias_key
].empty()) {
862 ip_aliases_
.erase(ip_alias_key
);
865 session_aliases_
.erase(session
);
868 void QuicStreamFactory::OnSessionClosed(QuicClientSession
* session
) {
869 DCHECK_EQ(0u, session
->GetNumOpenStreams());
870 OnSessionGoingAway(session
);
872 all_sessions_
.erase(session
);
875 void QuicStreamFactory::OnSessionConnectTimeout(
876 QuicClientSession
* session
) {
877 const AliasSet
& aliases
= session_aliases_
[session
];
878 for (AliasSet::const_iterator it
= aliases
.begin(); it
!= aliases
.end();
880 DCHECK(active_sessions_
.count(*it
));
881 DCHECK_EQ(session
, active_sessions_
[*it
]);
882 active_sessions_
.erase(*it
);
885 if (aliases
.empty()) {
889 const IpAliasKey
ip_alias_key(session
->connection()->peer_address(),
890 aliases
.begin()->is_https());
891 ip_aliases_
[ip_alias_key
].erase(session
);
892 if (ip_aliases_
[ip_alias_key
].empty()) {
893 ip_aliases_
.erase(ip_alias_key
);
895 QuicServerId server_id
= *aliases
.begin();
896 session_aliases_
.erase(session
);
897 Job
* job
= new Job(this, host_resolver_
, session
, server_id
);
898 active_jobs_
[server_id
].insert(job
);
899 int rv
= job
->Run(base::Bind(&QuicStreamFactory::OnJobComplete
,
900 base::Unretained(this), job
));
901 DCHECK_EQ(ERR_IO_PENDING
, rv
);
904 void QuicStreamFactory::CancelRequest(QuicStreamRequest
* request
) {
905 DCHECK(ContainsKey(active_requests_
, request
));
906 QuicServerId server_id
= active_requests_
[request
];
907 job_requests_map_
[server_id
].erase(request
);
908 active_requests_
.erase(request
);
911 void QuicStreamFactory::CloseAllSessions(int error
) {
912 while (!active_sessions_
.empty()) {
913 size_t initial_size
= active_sessions_
.size();
914 active_sessions_
.begin()->second
->CloseSessionOnError(error
);
915 DCHECK_NE(initial_size
, active_sessions_
.size());
917 while (!all_sessions_
.empty()) {
918 size_t initial_size
= all_sessions_
.size();
919 all_sessions_
.begin()->first
->CloseSessionOnError(error
);
920 DCHECK_NE(initial_size
, all_sessions_
.size());
922 DCHECK(all_sessions_
.empty());
925 base::Value
* QuicStreamFactory::QuicStreamFactoryInfoToValue() const {
926 base::ListValue
* list
= new base::ListValue();
928 for (SessionMap::const_iterator it
= active_sessions_
.begin();
929 it
!= active_sessions_
.end(); ++it
) {
930 const QuicServerId
& server_id
= it
->first
;
931 QuicClientSession
* session
= it
->second
;
932 const AliasSet
& aliases
= session_aliases_
.find(session
)->second
;
933 // Only add a session to the list once.
934 if (server_id
== *aliases
.begin()) {
935 std::set
<HostPortPair
> hosts
;
936 for (AliasSet::const_iterator alias_it
= aliases
.begin();
937 alias_it
!= aliases
.end(); ++alias_it
) {
938 hosts
.insert(alias_it
->host_port_pair());
940 list
->Append(session
->GetInfoAsValue(hosts
));
946 void QuicStreamFactory::ClearCachedStatesInCryptoConfig() {
947 crypto_config_
.ClearCachedStates();
950 void QuicStreamFactory::OnIPAddressChanged() {
951 CloseAllSessions(ERR_NETWORK_CHANGED
);
952 set_require_confirmation(true);
955 void QuicStreamFactory::OnCertAdded(const X509Certificate
* cert
) {
956 CloseAllSessions(ERR_CERT_DATABASE_CHANGED
);
959 void QuicStreamFactory::OnCACertChanged(const X509Certificate
* cert
) {
960 // We should flush the sessions if we removed trust from a
961 // cert, because a previously trusted server may have become
964 // We should not flush the sessions if we added trust to a cert.
966 // Since the OnCACertChanged method doesn't tell us what
967 // kind of change it is, we have to flush the socket
969 CloseAllSessions(ERR_CERT_DATABASE_CHANGED
);
972 bool QuicStreamFactory::HasActiveSession(
973 const QuicServerId
& server_id
) const {
974 return ContainsKey(active_sessions_
, server_id
);
977 bool QuicStreamFactory::HasActiveJob(const QuicServerId
& key
) const {
978 return ContainsKey(active_jobs_
, key
);
981 int QuicStreamFactory::CreateSession(const QuicServerId
& server_id
,
982 scoped_ptr
<QuicServerInfo
> server_info
,
983 const AddressList
& address_list
,
984 base::TimeTicks dns_resolution_end_time
,
985 const BoundNetLog
& net_log
,
986 QuicClientSession
** session
) {
987 // TODO(vadimt): Remove ScopedTracker below once crbug.com/422516 is fixed.
988 tracked_objects::ScopedTracker
tracking_profile1(
989 FROM_HERE_WITH_EXPLICIT_FUNCTION(
990 "422516 QuicStreamFactory::CreateSession1"));
992 bool enable_port_selection
= enable_port_selection_
;
993 if (enable_port_selection
&&
994 ContainsKey(gone_away_aliases_
, server_id
)) {
995 // Disable port selection when the server is going away.
996 // There is no point in trying to return to the same server, if
997 // that server is no longer handling requests.
998 enable_port_selection
= false;
999 gone_away_aliases_
.erase(server_id
);
1002 QuicConnectionId connection_id
= random_generator_
->RandUint64();
1003 IPEndPoint addr
= *address_list
.begin();
1004 scoped_refptr
<PortSuggester
> port_suggester
=
1005 new PortSuggester(server_id
.host_port_pair(), port_seed_
);
1006 DatagramSocket::BindType bind_type
= enable_port_selection
?
1007 DatagramSocket::RANDOM_BIND
: // Use our callback.
1008 DatagramSocket::DEFAULT_BIND
; // Use OS to randomize.
1009 scoped_ptr
<DatagramClientSocket
> socket(
1010 client_socket_factory_
->CreateDatagramClientSocket(
1012 base::Bind(&PortSuggester::SuggestPort
, port_suggester
),
1013 net_log
.net_log(), net_log
.source()));
1015 if (enable_non_blocking_io_
&&
1016 client_socket_factory_
== ClientSocketFactory::GetDefaultFactory()) {
1018 static_cast<UDPClientSocket
*>(socket
.get())->UseNonBlockingIO();
1022 // TODO(vadimt): Remove ScopedTracker below once crbug.com/422516 is fixed.
1023 tracked_objects::ScopedTracker
tracking_profile2(
1024 FROM_HERE_WITH_EXPLICIT_FUNCTION(
1025 "422516 QuicStreamFactory::CreateSession2"));
1027 int rv
= socket
->Connect(addr
);
1029 // TODO(vadimt): Remove ScopedTracker below once crbug.com/422516 is fixed.
1030 tracked_objects::ScopedTracker
tracking_profile3(
1031 FROM_HERE_WITH_EXPLICIT_FUNCTION(
1032 "422516 QuicStreamFactory::CreateSession3"));
1035 HistogramCreateSessionFailure(CREATION_ERROR_CONNECTING_SOCKET
);
1038 UMA_HISTOGRAM_COUNTS("Net.QuicEphemeralPortsSuggested",
1039 port_suggester
->call_count());
1040 if (enable_port_selection
) {
1041 DCHECK_LE(1u, port_suggester
->call_count());
1043 DCHECK_EQ(0u, port_suggester
->call_count());
1046 rv
= socket
->SetReceiveBufferSize(socket_receive_buffer_size_
);
1048 HistogramCreateSessionFailure(CREATION_ERROR_SETTING_RECEIVE_BUFFER
);
1051 // Set a buffer large enough to contain the initial CWND's worth of packet
1052 // to work around the problem with CHLO packets being sent out with the
1053 // wrong encryption level, when the send buffer is full.
1054 rv
= socket
->SetSendBufferSize(kMaxPacketSize
* 20);
1056 HistogramCreateSessionFailure(CREATION_ERROR_SETTING_SEND_BUFFER
);
1060 socket
->GetLocalAddress(&local_address_
);
1061 if (check_persisted_supports_quic_
&& http_server_properties_
) {
1062 check_persisted_supports_quic_
= false;
1063 IPAddressNumber last_address
;
1064 if (http_server_properties_
->GetSupportsQuic(&last_address
) &&
1065 last_address
== local_address_
.address()) {
1066 require_confirmation_
= false;
1070 DefaultPacketWriterFactory
packet_writer_factory(socket
.get());
1072 if (!helper_
.get()) {
1073 helper_
.reset(new QuicConnectionHelper(
1074 base::MessageLoop::current()->message_loop_proxy().get(),
1075 clock_
.get(), random_generator_
));
1078 // TODO(vadimt): Remove ScopedTracker below once crbug.com/422516 is fixed.
1079 tracked_objects::ScopedTracker
tracking_profile4(
1080 FROM_HERE_WITH_EXPLICIT_FUNCTION(
1081 "422516 QuicStreamFactory::CreateSession4"));
1083 QuicConnection
* connection
= new QuicConnection(connection_id
,
1086 packet_writer_factory
,
1087 true /* owns_writer */,
1088 false /* is_server */,
1089 server_id
.is_https(),
1090 supported_versions_
);
1091 connection
->set_max_packet_length(max_packet_length_
);
1093 // TODO(vadimt): Remove ScopedTracker below once crbug.com/422516 is fixed.
1094 tracked_objects::ScopedTracker
tracking_profile5(
1095 FROM_HERE_WITH_EXPLICIT_FUNCTION(
1096 "422516 QuicStreamFactory::CreateSession5"));
1098 InitializeCachedStateInCryptoConfig(server_id
, server_info
);
1100 // TODO(vadimt): Remove ScopedTracker below once crbug.com/422516 is fixed.
1101 tracked_objects::ScopedTracker
tracking_profile51(
1102 FROM_HERE_WITH_EXPLICIT_FUNCTION(
1103 "422516 QuicStreamFactory::CreateSession51"));
1105 QuicConfig config
= config_
;
1107 config
.SetSocketReceiveBufferToSend(socket_receive_buffer_size_
);
1109 // TODO(vadimt): Remove ScopedTracker below once crbug.com/422516 is fixed.
1110 tracked_objects::ScopedTracker
tracking_profile52(
1111 FROM_HERE_WITH_EXPLICIT_FUNCTION(
1112 "422516 QuicStreamFactory::CreateSession52"));
1114 config
.set_max_undecryptable_packets(kMaxUndecryptablePackets
);
1116 // TODO(vadimt): Remove ScopedTracker below once crbug.com/422516 is fixed.
1117 tracked_objects::ScopedTracker
tracking_profile53(
1118 FROM_HERE_WITH_EXPLICIT_FUNCTION(
1119 "422516 QuicStreamFactory::CreateSession53"));
1121 config
.SetInitialStreamFlowControlWindowToSend(kInitialReceiveWindowSize
);
1123 // TODO(vadimt): Remove ScopedTracker below once crbug.com/422516 is fixed.
1124 tracked_objects::ScopedTracker
tracking_profile54(
1125 FROM_HERE_WITH_EXPLICIT_FUNCTION(
1126 "422516 QuicStreamFactory::CreateSession54"));
1128 config
.SetInitialSessionFlowControlWindowToSend(kInitialReceiveWindowSize
);
1130 // TODO(vadimt): Remove ScopedTracker below once crbug.com/422516 is fixed.
1131 tracked_objects::ScopedTracker
tracking_profile55(
1132 FROM_HERE_WITH_EXPLICIT_FUNCTION(
1133 "422516 QuicStreamFactory::CreateSession55"));
1135 int64 srtt
= GetServerNetworkStatsSmoothedRttInMicroseconds(server_id
);
1137 // TODO(vadimt): Remove ScopedTracker below once crbug.com/422516 is fixed.
1138 tracked_objects::ScopedTracker
tracking_profile56(
1139 FROM_HERE_WITH_EXPLICIT_FUNCTION(
1140 "422516 QuicStreamFactory::CreateSession56"));
1143 config
.SetInitialRoundTripTimeUsToSend(static_cast<uint32
>(srtt
));
1145 // TODO(vadimt): Remove ScopedTracker below once crbug.com/422516 is fixed.
1146 tracked_objects::ScopedTracker
tracking_profile57(
1147 FROM_HERE_WITH_EXPLICIT_FUNCTION(
1148 "422516 QuicStreamFactory::CreateSession57"));
1150 config
.SetBytesForConnectionIdToSend(0);
1152 if (quic_server_info_factory_
&& !server_info
) {
1153 // TODO(vadimt): Remove ScopedTracker below once crbug.com/422516 is fixed.
1154 tracked_objects::ScopedTracker
tracking_profile6(
1155 FROM_HERE_WITH_EXPLICIT_FUNCTION(
1156 "422516 QuicStreamFactory::CreateSession6"));
1158 // Start the disk cache loading so that we can persist the newer QUIC server
1159 // information and/or inform the disk cache that we have reused
1161 server_info
.reset(quic_server_info_factory_
->GetForServer(server_id
));
1162 server_info
->Start();
1165 // TODO(vadimt): Remove ScopedTracker below once crbug.com/422516 is fixed.
1166 tracked_objects::ScopedTracker
tracking_profile61(
1167 FROM_HERE_WITH_EXPLICIT_FUNCTION(
1168 "422516 QuicStreamFactory::CreateSession61"));
1170 *session
= new QuicClientSession(
1171 connection
, socket
.Pass(), this, transport_security_state_
,
1172 server_info
.Pass(), config
, network_connection_
.GetDescription(),
1173 dns_resolution_end_time
,
1174 base::MessageLoop::current()->message_loop_proxy().get(),
1177 // TODO(rtenneti): Remove ScopedTracker below once crbug.com/422516 is fixed.
1178 tracked_objects::ScopedTracker
tracking_profile62(
1179 FROM_HERE_WITH_EXPLICIT_FUNCTION(
1180 "422516 QuicStreamFactory::CreateSession62"));
1182 all_sessions_
[*session
] = server_id
; // owning pointer
1184 // TODO(vadimt): Remove ScopedTracker below once crbug.com/422516 is fixed.
1185 tracked_objects::ScopedTracker
tracking_profile7(
1186 FROM_HERE_WITH_EXPLICIT_FUNCTION(
1187 "422516 QuicStreamFactory::CreateSession7"));
1189 (*session
)->InitializeSession(server_id
, &crypto_config_
,
1190 quic_crypto_client_stream_factory_
);
1191 bool closed_during_initialize
=
1192 !ContainsKey(all_sessions_
, *session
) ||
1193 !(*session
)->connection()->connected();
1194 UMA_HISTOGRAM_BOOLEAN("Net.QuicSession.ClosedDuringInitializeSession",
1195 closed_during_initialize
);
1196 if (closed_during_initialize
) {
1197 DLOG(DFATAL
) << "Session closed during initialize";
1199 return ERR_CONNECTION_CLOSED
;
1204 void QuicStreamFactory::ActivateSession(
1205 const QuicServerId
& server_id
,
1206 QuicClientSession
* session
) {
1207 DCHECK(!HasActiveSession(server_id
));
1208 UMA_HISTOGRAM_COUNTS("Net.QuicActiveSessions", active_sessions_
.size());
1209 active_sessions_
[server_id
] = session
;
1210 session_aliases_
[session
].insert(server_id
);
1211 const IpAliasKey
ip_alias_key(session
->connection()->peer_address(),
1212 server_id
.is_https());
1213 DCHECK(!ContainsKey(ip_aliases_
[ip_alias_key
], session
));
1214 ip_aliases_
[ip_alias_key
].insert(session
);
1217 int64
QuicStreamFactory::GetServerNetworkStatsSmoothedRttInMicroseconds(
1218 const QuicServerId
& server_id
) const {
1219 if (!http_server_properties_
)
1221 const ServerNetworkStats
* stats
=
1222 http_server_properties_
->GetServerNetworkStats(
1223 server_id
.host_port_pair());
1224 if (stats
== nullptr)
1226 return stats
->srtt
.InMicroseconds();
1229 bool QuicStreamFactory::WasAlternateProtocolRecentlyBroken(
1230 const QuicServerId
& server_id
) const {
1231 return http_server_properties_
&&
1232 http_server_properties_
->WasAlternateProtocolRecentlyBroken(
1233 server_id
.host_port_pair());
1236 bool QuicStreamFactory::CryptoConfigCacheIsEmpty(
1237 const QuicServerId
& server_id
) {
1238 QuicCryptoClientConfig::CachedState
* cached
=
1239 crypto_config_
.LookupOrCreate(server_id
);
1240 return cached
->IsEmpty();
1243 void QuicStreamFactory::InitializeCachedStateInCryptoConfig(
1244 const QuicServerId
& server_id
,
1245 const scoped_ptr
<QuicServerInfo
>& server_info
) {
1246 // TODO(vadimt): Remove ScopedTracker below once crbug.com/422516 is fixed.
1247 tracked_objects::ScopedTracker
tracking_profile1(
1248 FROM_HERE_WITH_EXPLICIT_FUNCTION(
1249 "422516 QuicStreamFactory::InitializeCachedStateInCryptoConfig1"));
1251 // |server_info| will be NULL, if a non-empty server config already exists in
1252 // the memory cache. This is a minor optimization to avoid LookupOrCreate.
1256 QuicCryptoClientConfig::CachedState
* cached
=
1257 crypto_config_
.LookupOrCreate(server_id
);
1258 if (!cached
->IsEmpty())
1261 if (http_server_properties_
) {
1262 if (quic_supported_servers_at_startup_
.empty()) {
1263 for (const std::pair
<const HostPortPair
, AlternateProtocolInfo
>&
1264 key_value
: http_server_properties_
->alternate_protocol_map()) {
1265 if (key_value
.second
.protocol
== QUIC
) {
1266 quic_supported_servers_at_startup_
.insert(key_value
.first
);
1271 // TODO(rtenneti): Delete the following histogram after collecting stats.
1272 // If the AlternateProtocolMap contained an entry for this host, check if
1273 // the disk cache contained an entry for it.
1274 if (ContainsKey(quic_supported_servers_at_startup_
,
1275 server_id
.host_port_pair())) {
1276 UMA_HISTOGRAM_BOOLEAN(
1277 "Net.QuicServerInfo.ExpectConfigMissingFromDiskCache",
1278 server_info
->state().server_config
.empty());
1282 // TODO(vadimt): Remove ScopedTracker below once crbug.com/422516 is fixed.
1283 tracked_objects::ScopedTracker
tracking_profile2(
1284 FROM_HERE_WITH_EXPLICIT_FUNCTION(
1285 "422516 QuicStreamFactory::InitializeCachedStateInCryptoConfig2"));
1287 if (!cached
->Initialize(server_info
->state().server_config
,
1288 server_info
->state().source_address_token
,
1289 server_info
->state().certs
,
1290 server_info
->state().server_config_sig
,
1294 if (!server_id
.is_https()) {
1295 // Don't check the certificates for insecure QUIC.
1296 cached
->SetProofValid();
1300 void QuicStreamFactory::ProcessGoingAwaySession(
1301 QuicClientSession
* session
,
1302 const QuicServerId
& server_id
,
1303 bool session_was_active
) {
1304 if (!http_server_properties_
)
1307 const QuicConnectionStats
& stats
= session
->connection()->GetStats();
1308 if (session
->IsCryptoHandshakeConfirmed()) {
1309 ServerNetworkStats network_stats
;
1310 network_stats
.srtt
= base::TimeDelta::FromMicroseconds(stats
.srtt_us
);
1311 network_stats
.bandwidth_estimate
= stats
.estimated_bandwidth
;
1312 http_server_properties_
->SetServerNetworkStats(server_id
.host_port_pair(),
1317 UMA_HISTOGRAM_COUNTS("Net.QuicHandshakeNotConfirmedNumPacketsReceived",
1318 stats
.packets_received
);
1320 if (!session_was_active
)
1323 const HostPortPair
& server
= server_id
.host_port_pair();
1324 // Don't try to change the alternate-protocol state, if the
1325 // alternate-protocol state is unknown.
1326 const AlternateProtocolInfo alternate
=
1327 http_server_properties_
->GetAlternateProtocol(server
);
1328 if (alternate
.protocol
== UNINITIALIZED_ALTERNATE_PROTOCOL
)
1331 // TODO(rch): In the special case where the session has received no
1332 // packets from the peer, we should consider blacklisting this
1333 // differently so that we still race TCP but we don't consider the
1334 // session connected until the handshake has been confirmed.
1335 HistogramBrokenAlternateProtocolLocation(
1336 BROKEN_ALTERNATE_PROTOCOL_LOCATION_QUIC_STREAM_FACTORY
);
1337 DCHECK_EQ(QUIC
, alternate
.protocol
);
1339 // Since the session was active, there's no longer an
1340 // HttpStreamFactoryImpl::Job running which can mark it broken, unless the
1341 // TCP job also fails. So to avoid not using QUIC when we otherwise could,
1342 // we mark it as broken, and then immediately re-enable it. This leaves
1343 // QUIC as "recently broken" which means that 0-RTT will be disabled but
1344 // we'll still race.
1345 http_server_properties_
->SetBrokenAlternateProtocol(server
);
1346 http_server_properties_
->ClearAlternateProtocol(server
);
1347 http_server_properties_
->SetAlternateProtocol(
1348 server
, alternate
.port
, alternate
.protocol
, 1);
1350 http_server_properties_
->GetAlternateProtocol(server
).protocol
);
1351 DCHECK(http_server_properties_
->WasAlternateProtocolRecentlyBroken(