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 int64 load_server_info_timeout_ms
= factory_
->load_server_info_timeout_ms_
;
399 if (factory_
->load_server_info_timeout_srtt_multiplier_
> 0) {
400 DCHECK_EQ(0, load_server_info_timeout_ms
);
401 load_server_info_timeout_ms
=
402 (factory_
->load_server_info_timeout_srtt_multiplier_
*
403 factory_
->GetServerNetworkStatsSmoothedRttInMicroseconds(server_id_
)) /
406 if (load_server_info_timeout_ms
> 0) {
407 factory_
->task_runner_
->PostDelayedTask(
409 base::Bind(&QuicStreamFactory::Job::CancelWaitForDataReadyCallback
,
411 base::TimeDelta::FromMilliseconds(load_server_info_timeout_ms
));
414 int rv
= server_info_
->WaitForDataReady(
415 base::Bind(&QuicStreamFactory::Job::OnIOComplete
, GetWeakPtr()));
416 if (rv
== ERR_IO_PENDING
&& factory_
->enable_connection_racing()) {
417 // If we are waiting to load server config from the disk cache, then start
419 started_another_job_
= true;
420 factory_
->CreateAuxilaryJob(server_id_
, is_post_
, net_log_
);
425 int QuicStreamFactory::Job::DoLoadServerInfoComplete(int rv
) {
426 // TODO(vadimt): Remove ScopedTracker below once crbug.com/422516 is fixed.
427 tracked_objects::ScopedTracker
tracking_profile(
428 FROM_HERE_WITH_EXPLICIT_FUNCTION(
429 "422516 QuicStreamFactory::Job::DoLoadServerInfoComplete"));
431 UMA_HISTOGRAM_TIMES("Net.QuicServerInfo.DiskCacheWaitForDataReadyTime",
432 base::TimeTicks::Now() - dns_resolution_end_time_
);
435 server_info_
.reset();
437 if (started_another_job_
&&
438 (!server_info_
|| server_info_
->state().server_config
.empty() ||
439 !factory_
->CryptoConfigCacheIsEmpty(server_id_
))) {
440 // If we have started another job and if we didn't load the server config
441 // from the disk cache or if we have received a new server config from the
442 // server, then cancel the current job.
443 io_state_
= STATE_NONE
;
444 return ERR_CONNECTION_CLOSED
;
447 io_state_
= STATE_CONNECT
;
451 int QuicStreamFactory::Job::DoConnect() {
452 // TODO(vadimt): Remove ScopedTracker below once crbug.com/422516 is fixed.
453 tracked_objects::ScopedTracker
tracking_profile(
454 FROM_HERE_WITH_EXPLICIT_FUNCTION(
455 "422516 QuicStreamFactory::Job::DoConnect"));
457 io_state_
= STATE_CONNECT_COMPLETE
;
460 factory_
->CreateSession(server_id_
, server_info_
.Pass(), address_list_
,
461 dns_resolution_end_time_
, net_log_
, &session_
);
463 DCHECK(rv
!= ERR_IO_PENDING
);
468 if (!session_
->connection()->connected()) {
469 return ERR_CONNECTION_CLOSED
;
472 // TODO(vadimt): Remove ScopedTracker below once crbug.com/422516 is fixed.
473 tracked_objects::ScopedTracker
tracking_profile1(
474 FROM_HERE_WITH_EXPLICIT_FUNCTION(
475 "422516 QuicStreamFactory::Job::DoConnect1"));
477 session_
->StartReading();
478 if (!session_
->connection()->connected()) {
479 return ERR_QUIC_PROTOCOL_ERROR
;
481 bool require_confirmation
=
482 factory_
->require_confirmation() || is_post_
||
483 was_alternate_protocol_recently_broken_
;
485 // TODO(vadimt): Remove ScopedTracker below once crbug.com/422516 is fixed.
486 tracked_objects::ScopedTracker
tracking_profile2(
487 FROM_HERE_WITH_EXPLICIT_FUNCTION(
488 "422516 QuicStreamFactory::Job::DoConnect2"));
490 rv
= session_
->CryptoConnect(
491 require_confirmation
,
492 base::Bind(&QuicStreamFactory::Job::OnIOComplete
, GetWeakPtr()));
496 int QuicStreamFactory::Job::DoResumeConnect() {
497 // TODO(vadimt): Remove ScopedTracker below once crbug.com/422516 is fixed.
498 tracked_objects::ScopedTracker
tracking_profile(
499 FROM_HERE_WITH_EXPLICIT_FUNCTION(
500 "422516 QuicStreamFactory::Job::DoResumeConnect"));
502 io_state_
= STATE_CONNECT_COMPLETE
;
504 int rv
= session_
->ResumeCryptoConnect(
505 base::Bind(&QuicStreamFactory::Job::OnIOComplete
, GetWeakPtr()));
510 int QuicStreamFactory::Job::DoConnectComplete(int rv
) {
511 // TODO(vadimt): Remove ScopedTracker below once crbug.com/422516 is fixed.
512 tracked_objects::ScopedTracker
tracking_profile(
513 FROM_HERE_WITH_EXPLICIT_FUNCTION(
514 "422516 QuicStreamFactory::Job::DoConnectComplete"));
519 DCHECK(!factory_
->HasActiveSession(server_id_
));
520 // There may well now be an active session for this IP. If so, use the
521 // existing session instead.
522 AddressList
address(session_
->connection()->peer_address());
523 if (factory_
->OnResolution(server_id_
, address
)) {
524 session_
->connection()->SendConnectionClose(QUIC_CONNECTION_IP_POOLED
);
529 factory_
->ActivateSession(server_id_
, session_
);
534 QuicStreamRequest::QuicStreamRequest(QuicStreamFactory
* factory
)
535 : factory_(factory
) {}
537 QuicStreamRequest::~QuicStreamRequest() {
538 if (factory_
&& !callback_
.is_null())
539 factory_
->CancelRequest(this);
542 int QuicStreamRequest::Request(const HostPortPair
& host_port_pair
,
544 PrivacyMode privacy_mode
,
545 base::StringPiece method
,
546 const BoundNetLog
& net_log
,
547 const CompletionCallback
& callback
) {
549 DCHECK(callback_
.is_null());
551 int rv
= factory_
->Create(host_port_pair
, is_https
, privacy_mode
, method
,
553 if (rv
== ERR_IO_PENDING
) {
554 host_port_pair_
= host_port_pair
;
555 is_https_
= is_https
;
557 callback_
= callback
;
566 void QuicStreamRequest::set_stream(scoped_ptr
<QuicHttpStream
> stream
) {
568 stream_
= stream
.Pass();
571 void QuicStreamRequest::OnRequestComplete(int rv
) {
576 scoped_ptr
<QuicHttpStream
> QuicStreamRequest::ReleaseStream() {
578 return stream_
.Pass();
581 QuicStreamFactory::QuicStreamFactory(
582 HostResolver
* host_resolver
,
583 ClientSocketFactory
* client_socket_factory
,
584 base::WeakPtr
<HttpServerProperties
> http_server_properties
,
585 CertVerifier
* cert_verifier
,
586 ChannelIDService
* channel_id_service
,
587 TransportSecurityState
* transport_security_state
,
588 QuicCryptoClientStreamFactory
* quic_crypto_client_stream_factory
,
589 QuicRandom
* random_generator
,
591 size_t max_packet_length
,
592 const std::string
& user_agent_id
,
593 const QuicVersionVector
& supported_versions
,
594 bool enable_port_selection
,
595 bool always_require_handshake_confirmation
,
596 bool disable_connection_pooling
,
597 int load_server_info_timeout
,
598 float load_server_info_timeout_srtt_multiplier
,
599 bool enable_truncated_connection_ids
,
600 bool enable_connection_racing
,
601 bool enable_non_blocking_io
,
602 bool disable_disk_cache
,
603 int socket_receive_buffer_size
,
604 const QuicTagVector
& connection_options
)
605 : require_confirmation_(true),
606 host_resolver_(host_resolver
),
607 client_socket_factory_(client_socket_factory
),
608 http_server_properties_(http_server_properties
),
609 transport_security_state_(transport_security_state
),
610 quic_server_info_factory_(nullptr),
611 quic_crypto_client_stream_factory_(quic_crypto_client_stream_factory
),
612 random_generator_(random_generator
),
614 max_packet_length_(max_packet_length
),
615 config_(InitializeQuicConfig(connection_options
)),
616 supported_versions_(supported_versions
),
617 enable_port_selection_(enable_port_selection
),
618 always_require_handshake_confirmation_(
619 always_require_handshake_confirmation
),
620 disable_connection_pooling_(disable_connection_pooling
),
621 load_server_info_timeout_ms_(load_server_info_timeout
),
622 load_server_info_timeout_srtt_multiplier_(
623 load_server_info_timeout_srtt_multiplier
),
624 enable_truncated_connection_ids_(enable_truncated_connection_ids
),
625 enable_connection_racing_(enable_connection_racing
),
626 enable_non_blocking_io_(enable_non_blocking_io
),
627 disable_disk_cache_(disable_disk_cache
),
628 socket_receive_buffer_size_(socket_receive_buffer_size
),
629 port_seed_(random_generator_
->RandUint64()),
630 check_persisted_supports_quic_(true),
631 task_runner_(nullptr),
632 weak_factory_(this) {
633 DCHECK(transport_security_state_
);
634 crypto_config_
.set_user_agent_id(user_agent_id
);
635 crypto_config_
.AddCanonicalSuffix(".c.youtube.com");
636 crypto_config_
.AddCanonicalSuffix(".googlevideo.com");
637 crypto_config_
.SetProofVerifier(
638 new ProofVerifierChromium(cert_verifier
, transport_security_state
));
639 crypto_config_
.SetChannelIDSource(
640 new ChannelIDSourceChromium(channel_id_service
));
642 if (cpu
.has_aesni() && cpu
.has_avx())
643 crypto_config_
.PreferAesGcm();
644 if (!IsEcdsaSupported())
645 crypto_config_
.DisableEcdsa();
648 QuicStreamFactory::~QuicStreamFactory() {
649 CloseAllSessions(ERR_ABORTED
);
650 while (!all_sessions_
.empty()) {
651 delete all_sessions_
.begin()->first
;
652 all_sessions_
.erase(all_sessions_
.begin());
654 while (!active_jobs_
.empty()) {
655 const QuicServerId server_id
= active_jobs_
.begin()->first
;
656 STLDeleteElements(&(active_jobs_
[server_id
]));
657 active_jobs_
.erase(server_id
);
661 void QuicStreamFactory::set_require_confirmation(bool require_confirmation
) {
662 require_confirmation_
= require_confirmation
;
663 if (http_server_properties_
&& (!(local_address_
== IPEndPoint()))) {
664 http_server_properties_
->SetSupportsQuic(!require_confirmation
,
665 local_address_
.address());
669 int QuicStreamFactory::Create(const HostPortPair
& host_port_pair
,
671 PrivacyMode privacy_mode
,
672 base::StringPiece method
,
673 const BoundNetLog
& net_log
,
674 QuicStreamRequest
* request
) {
675 QuicServerId
server_id(host_port_pair
, is_https
, privacy_mode
);
676 if (HasActiveSession(server_id
)) {
677 request
->set_stream(CreateIfSessionExists(server_id
, net_log
));
681 if (HasActiveJob(server_id
)) {
682 active_requests_
[request
] = server_id
;
683 job_requests_map_
[server_id
].insert(request
);
684 return ERR_IO_PENDING
;
687 // TODO(rtenneti): |task_runner_| is used by the Job. Initialize task_runner_
688 // in the constructor after WebRequestActionWithThreadsTest.* tests are fixed.
690 task_runner_
= base::MessageLoop::current()->message_loop_proxy().get();
692 QuicServerInfo
* quic_server_info
= nullptr;
693 if (quic_server_info_factory_
) {
694 bool load_from_disk_cache
= !disable_disk_cache_
;
695 if (http_server_properties_
) {
696 const AlternateProtocolMap
& alternate_protocol_map
=
697 http_server_properties_
->alternate_protocol_map();
698 AlternateProtocolMap::const_iterator it
=
699 alternate_protocol_map
.Peek(server_id
.host_port_pair());
700 if (it
== alternate_protocol_map
.end() || it
->second
.protocol
!= QUIC
) {
701 // If there is no entry for QUIC, consider that as a new server and
702 // don't wait for Cache thread to load the data for that server.
703 load_from_disk_cache
= false;
706 if (load_from_disk_cache
&& CryptoConfigCacheIsEmpty(server_id
)) {
707 quic_server_info
= quic_server_info_factory_
->GetForServer(server_id
);
711 scoped_ptr
<Job
> job(new Job(this, host_resolver_
, host_port_pair
, is_https
,
712 WasAlternateProtocolRecentlyBroken(server_id
),
713 privacy_mode
, method
== "POST" /* is_post */,
714 quic_server_info
, net_log
));
715 int rv
= job
->Run(base::Bind(&QuicStreamFactory::OnJobComplete
,
716 base::Unretained(this), job
.get()));
717 if (rv
== ERR_IO_PENDING
) {
718 active_requests_
[request
] = server_id
;
719 job_requests_map_
[server_id
].insert(request
);
720 active_jobs_
[server_id
].insert(job
.release());
724 DCHECK(HasActiveSession(server_id
));
725 request
->set_stream(CreateIfSessionExists(server_id
, net_log
));
730 void QuicStreamFactory::CreateAuxilaryJob(const QuicServerId server_id
,
732 const BoundNetLog
& net_log
) {
733 Job
* aux_job
= new Job(this, host_resolver_
, server_id
.host_port_pair(),
734 server_id
.is_https(),
735 WasAlternateProtocolRecentlyBroken(server_id
),
736 server_id
.privacy_mode(), is_post
, nullptr, net_log
);
737 active_jobs_
[server_id
].insert(aux_job
);
738 task_runner_
->PostTask(FROM_HERE
,
739 base::Bind(&QuicStreamFactory::Job::RunAuxilaryJob
,
740 aux_job
->GetWeakPtr()));
743 bool QuicStreamFactory::OnResolution(
744 const QuicServerId
& server_id
,
745 const AddressList
& address_list
) {
746 DCHECK(!HasActiveSession(server_id
));
747 if (disable_connection_pooling_
) {
750 for (const IPEndPoint
& address
: address_list
) {
751 const IpAliasKey
ip_alias_key(address
, server_id
.is_https());
752 if (!ContainsKey(ip_aliases_
, ip_alias_key
))
755 const SessionSet
& sessions
= ip_aliases_
[ip_alias_key
];
756 for (QuicClientSession
* session
: sessions
) {
757 if (!session
->CanPool(server_id
.host(), server_id
.privacy_mode()))
759 active_sessions_
[server_id
] = session
;
760 session_aliases_
[session
].insert(server_id
);
767 void QuicStreamFactory::OnJobComplete(Job
* job
, int rv
) {
768 QuicServerId server_id
= job
->server_id();
770 JobSet
* jobs
= &(active_jobs_
[server_id
]);
771 if (jobs
->size() > 1) {
772 // If there is another pending job, then we can delete this job and let
773 // the other job handle the request.
782 // TODO(vadimt): Remove ScopedTracker below once crbug.com/422516 is fixed.
783 tracked_objects::ScopedTracker
tracking_profile1(
784 FROM_HERE_WITH_EXPLICIT_FUNCTION(
785 "422516 QuicStreamFactory::OnJobComplete1"));
787 if (!always_require_handshake_confirmation_
)
788 set_require_confirmation(false);
790 // Create all the streams, but do not notify them yet.
791 for (QuicStreamRequest
* request
: job_requests_map_
[server_id
]) {
792 DCHECK(HasActiveSession(server_id
));
793 request
->set_stream(CreateIfSessionExists(server_id
, request
->net_log()));
797 // TODO(vadimt): Remove ScopedTracker below once crbug.com/422516 is fixed.
798 tracked_objects::ScopedTracker
tracking_profile2(
799 FROM_HERE_WITH_EXPLICIT_FUNCTION(
800 "422516 QuicStreamFactory::OnJobComplete2"));
802 while (!job_requests_map_
[server_id
].empty()) {
803 RequestSet::iterator it
= job_requests_map_
[server_id
].begin();
804 QuicStreamRequest
* request
= *it
;
805 job_requests_map_
[server_id
].erase(it
);
806 active_requests_
.erase(request
);
807 // Even though we're invoking callbacks here, we don't need to worry
808 // about |this| being deleted, because the factory is owned by the
809 // profile which can not be deleted via callbacks.
810 request
->OnRequestComplete(rv
);
813 // TODO(vadimt): Remove ScopedTracker below once crbug.com/422516 is fixed.
814 tracked_objects::ScopedTracker
tracking_profile3(
815 FROM_HERE_WITH_EXPLICIT_FUNCTION(
816 "422516 QuicStreamFactory::OnJobComplete3"));
818 for (Job
* other_job
: active_jobs_
[server_id
]) {
819 if (other_job
!= job
)
823 STLDeleteElements(&(active_jobs_
[server_id
]));
824 active_jobs_
.erase(server_id
);
825 job_requests_map_
.erase(server_id
);
828 // Returns a newly created QuicHttpStream owned by the caller, if a
829 // matching session already exists. Returns nullptr otherwise.
830 scoped_ptr
<QuicHttpStream
> QuicStreamFactory::CreateIfSessionExists(
831 const QuicServerId
& server_id
,
832 const BoundNetLog
& net_log
) {
833 if (!HasActiveSession(server_id
)) {
834 DVLOG(1) << "No active session";
835 return scoped_ptr
<QuicHttpStream
>();
838 QuicClientSession
* session
= active_sessions_
[server_id
];
840 return scoped_ptr
<QuicHttpStream
>(
841 new QuicHttpStream(session
->GetWeakPtr()));
844 void QuicStreamFactory::OnIdleSession(QuicClientSession
* session
) {
847 void QuicStreamFactory::OnSessionGoingAway(QuicClientSession
* session
) {
848 const AliasSet
& aliases
= session_aliases_
[session
];
849 for (AliasSet::const_iterator it
= aliases
.begin(); it
!= aliases
.end();
851 DCHECK(active_sessions_
.count(*it
));
852 DCHECK_EQ(session
, active_sessions_
[*it
]);
853 // Track sessions which have recently gone away so that we can disable
855 if (session
->goaway_received()) {
856 gone_away_aliases_
.insert(*it
);
859 active_sessions_
.erase(*it
);
860 ProcessGoingAwaySession(session
, *it
, true);
862 ProcessGoingAwaySession(session
, all_sessions_
[session
], false);
863 if (!aliases
.empty()) {
864 const IpAliasKey
ip_alias_key(session
->connection()->peer_address(),
865 aliases
.begin()->is_https());
866 ip_aliases_
[ip_alias_key
].erase(session
);
867 if (ip_aliases_
[ip_alias_key
].empty()) {
868 ip_aliases_
.erase(ip_alias_key
);
871 session_aliases_
.erase(session
);
874 void QuicStreamFactory::OnSessionClosed(QuicClientSession
* session
) {
875 DCHECK_EQ(0u, session
->GetNumOpenStreams());
876 OnSessionGoingAway(session
);
878 all_sessions_
.erase(session
);
881 void QuicStreamFactory::OnSessionConnectTimeout(
882 QuicClientSession
* session
) {
883 const AliasSet
& aliases
= session_aliases_
[session
];
884 for (AliasSet::const_iterator it
= aliases
.begin(); it
!= aliases
.end();
886 DCHECK(active_sessions_
.count(*it
));
887 DCHECK_EQ(session
, active_sessions_
[*it
]);
888 active_sessions_
.erase(*it
);
891 if (aliases
.empty()) {
895 const IpAliasKey
ip_alias_key(session
->connection()->peer_address(),
896 aliases
.begin()->is_https());
897 ip_aliases_
[ip_alias_key
].erase(session
);
898 if (ip_aliases_
[ip_alias_key
].empty()) {
899 ip_aliases_
.erase(ip_alias_key
);
901 QuicServerId server_id
= *aliases
.begin();
902 session_aliases_
.erase(session
);
903 Job
* job
= new Job(this, host_resolver_
, session
, server_id
);
904 active_jobs_
[server_id
].insert(job
);
905 int rv
= job
->Run(base::Bind(&QuicStreamFactory::OnJobComplete
,
906 base::Unretained(this), job
));
907 DCHECK_EQ(ERR_IO_PENDING
, rv
);
910 void QuicStreamFactory::CancelRequest(QuicStreamRequest
* request
) {
911 DCHECK(ContainsKey(active_requests_
, request
));
912 QuicServerId server_id
= active_requests_
[request
];
913 job_requests_map_
[server_id
].erase(request
);
914 active_requests_
.erase(request
);
917 void QuicStreamFactory::CloseAllSessions(int error
) {
918 while (!active_sessions_
.empty()) {
919 size_t initial_size
= active_sessions_
.size();
920 active_sessions_
.begin()->second
->CloseSessionOnError(error
);
921 DCHECK_NE(initial_size
, active_sessions_
.size());
923 while (!all_sessions_
.empty()) {
924 size_t initial_size
= all_sessions_
.size();
925 all_sessions_
.begin()->first
->CloseSessionOnError(error
);
926 DCHECK_NE(initial_size
, all_sessions_
.size());
928 DCHECK(all_sessions_
.empty());
931 base::Value
* QuicStreamFactory::QuicStreamFactoryInfoToValue() const {
932 base::ListValue
* list
= new base::ListValue();
934 for (SessionMap::const_iterator it
= active_sessions_
.begin();
935 it
!= active_sessions_
.end(); ++it
) {
936 const QuicServerId
& server_id
= it
->first
;
937 QuicClientSession
* session
= it
->second
;
938 const AliasSet
& aliases
= session_aliases_
.find(session
)->second
;
939 // Only add a session to the list once.
940 if (server_id
== *aliases
.begin()) {
941 std::set
<HostPortPair
> hosts
;
942 for (AliasSet::const_iterator alias_it
= aliases
.begin();
943 alias_it
!= aliases
.end(); ++alias_it
) {
944 hosts
.insert(alias_it
->host_port_pair());
946 list
->Append(session
->GetInfoAsValue(hosts
));
952 void QuicStreamFactory::ClearCachedStatesInCryptoConfig() {
953 crypto_config_
.ClearCachedStates();
956 void QuicStreamFactory::OnIPAddressChanged() {
957 CloseAllSessions(ERR_NETWORK_CHANGED
);
958 set_require_confirmation(true);
961 void QuicStreamFactory::OnCertAdded(const X509Certificate
* cert
) {
962 CloseAllSessions(ERR_CERT_DATABASE_CHANGED
);
965 void QuicStreamFactory::OnCACertChanged(const X509Certificate
* cert
) {
966 // We should flush the sessions if we removed trust from a
967 // cert, because a previously trusted server may have become
970 // We should not flush the sessions if we added trust to a cert.
972 // Since the OnCACertChanged method doesn't tell us what
973 // kind of change it is, we have to flush the socket
975 CloseAllSessions(ERR_CERT_DATABASE_CHANGED
);
978 bool QuicStreamFactory::HasActiveSession(
979 const QuicServerId
& server_id
) const {
980 return ContainsKey(active_sessions_
, server_id
);
983 bool QuicStreamFactory::HasActiveJob(const QuicServerId
& key
) const {
984 return ContainsKey(active_jobs_
, key
);
987 int QuicStreamFactory::CreateSession(const QuicServerId
& server_id
,
988 scoped_ptr
<QuicServerInfo
> server_info
,
989 const AddressList
& address_list
,
990 base::TimeTicks dns_resolution_end_time
,
991 const BoundNetLog
& net_log
,
992 QuicClientSession
** session
) {
993 // TODO(vadimt): Remove ScopedTracker below once crbug.com/422516 is fixed.
994 tracked_objects::ScopedTracker
tracking_profile1(
995 FROM_HERE_WITH_EXPLICIT_FUNCTION(
996 "422516 QuicStreamFactory::CreateSession1"));
998 bool enable_port_selection
= enable_port_selection_
;
999 if (enable_port_selection
&&
1000 ContainsKey(gone_away_aliases_
, server_id
)) {
1001 // Disable port selection when the server is going away.
1002 // There is no point in trying to return to the same server, if
1003 // that server is no longer handling requests.
1004 enable_port_selection
= false;
1005 gone_away_aliases_
.erase(server_id
);
1008 QuicConnectionId connection_id
= random_generator_
->RandUint64();
1009 IPEndPoint addr
= *address_list
.begin();
1010 scoped_refptr
<PortSuggester
> port_suggester
=
1011 new PortSuggester(server_id
.host_port_pair(), port_seed_
);
1012 DatagramSocket::BindType bind_type
= enable_port_selection
?
1013 DatagramSocket::RANDOM_BIND
: // Use our callback.
1014 DatagramSocket::DEFAULT_BIND
; // Use OS to randomize.
1015 scoped_ptr
<DatagramClientSocket
> socket(
1016 client_socket_factory_
->CreateDatagramClientSocket(
1018 base::Bind(&PortSuggester::SuggestPort
, port_suggester
),
1019 net_log
.net_log(), net_log
.source()));
1021 if (enable_non_blocking_io_
&&
1022 client_socket_factory_
== ClientSocketFactory::GetDefaultFactory()) {
1024 static_cast<UDPClientSocket
*>(socket
.get())->UseNonBlockingIO();
1028 // TODO(vadimt): Remove ScopedTracker below once crbug.com/422516 is fixed.
1029 tracked_objects::ScopedTracker
tracking_profile2(
1030 FROM_HERE_WITH_EXPLICIT_FUNCTION(
1031 "422516 QuicStreamFactory::CreateSession2"));
1033 int rv
= socket
->Connect(addr
);
1035 // TODO(vadimt): Remove ScopedTracker below once crbug.com/422516 is fixed.
1036 tracked_objects::ScopedTracker
tracking_profile3(
1037 FROM_HERE_WITH_EXPLICIT_FUNCTION(
1038 "422516 QuicStreamFactory::CreateSession3"));
1041 HistogramCreateSessionFailure(CREATION_ERROR_CONNECTING_SOCKET
);
1044 UMA_HISTOGRAM_COUNTS("Net.QuicEphemeralPortsSuggested",
1045 port_suggester
->call_count());
1046 if (enable_port_selection
) {
1047 DCHECK_LE(1u, port_suggester
->call_count());
1049 DCHECK_EQ(0u, port_suggester
->call_count());
1052 rv
= socket
->SetReceiveBufferSize(socket_receive_buffer_size_
);
1054 HistogramCreateSessionFailure(CREATION_ERROR_SETTING_RECEIVE_BUFFER
);
1057 // Set a buffer large enough to contain the initial CWND's worth of packet
1058 // to work around the problem with CHLO packets being sent out with the
1059 // wrong encryption level, when the send buffer is full.
1060 rv
= socket
->SetSendBufferSize(kMaxPacketSize
* 20);
1062 HistogramCreateSessionFailure(CREATION_ERROR_SETTING_SEND_BUFFER
);
1066 socket
->GetLocalAddress(&local_address_
);
1067 if (check_persisted_supports_quic_
&& http_server_properties_
) {
1068 check_persisted_supports_quic_
= false;
1069 IPAddressNumber last_address
;
1070 if (http_server_properties_
->GetSupportsQuic(&last_address
) &&
1071 last_address
== local_address_
.address()) {
1072 require_confirmation_
= false;
1076 DefaultPacketWriterFactory
packet_writer_factory(socket
.get());
1078 if (!helper_
.get()) {
1079 helper_
.reset(new QuicConnectionHelper(
1080 base::MessageLoop::current()->message_loop_proxy().get(),
1081 clock_
.get(), random_generator_
));
1084 // TODO(vadimt): Remove ScopedTracker below once crbug.com/422516 is fixed.
1085 tracked_objects::ScopedTracker
tracking_profile4(
1086 FROM_HERE_WITH_EXPLICIT_FUNCTION(
1087 "422516 QuicStreamFactory::CreateSession4"));
1089 QuicConnection
* connection
= new QuicConnection(connection_id
,
1092 packet_writer_factory
,
1093 true /* owns_writer */,
1094 false /* is_server */,
1095 server_id
.is_https(),
1096 supported_versions_
);
1097 connection
->set_max_packet_length(max_packet_length_
);
1099 // TODO(vadimt): Remove ScopedTracker below once crbug.com/422516 is fixed.
1100 tracked_objects::ScopedTracker
tracking_profile5(
1101 FROM_HERE_WITH_EXPLICIT_FUNCTION(
1102 "422516 QuicStreamFactory::CreateSession5"));
1104 InitializeCachedStateInCryptoConfig(server_id
, server_info
);
1106 // TODO(vadimt): Remove ScopedTracker below once crbug.com/422516 is fixed.
1107 tracked_objects::ScopedTracker
tracking_profile51(
1108 FROM_HERE_WITH_EXPLICIT_FUNCTION(
1109 "422516 QuicStreamFactory::CreateSession51"));
1111 QuicConfig config
= config_
;
1113 config
.SetSocketReceiveBufferToSend(socket_receive_buffer_size_
);
1115 // TODO(vadimt): Remove ScopedTracker below once crbug.com/422516 is fixed.
1116 tracked_objects::ScopedTracker
tracking_profile52(
1117 FROM_HERE_WITH_EXPLICIT_FUNCTION(
1118 "422516 QuicStreamFactory::CreateSession52"));
1120 config
.set_max_undecryptable_packets(kMaxUndecryptablePackets
);
1122 // TODO(vadimt): Remove ScopedTracker below once crbug.com/422516 is fixed.
1123 tracked_objects::ScopedTracker
tracking_profile53(
1124 FROM_HERE_WITH_EXPLICIT_FUNCTION(
1125 "422516 QuicStreamFactory::CreateSession53"));
1127 config
.SetInitialStreamFlowControlWindowToSend(kInitialReceiveWindowSize
);
1129 // TODO(vadimt): Remove ScopedTracker below once crbug.com/422516 is fixed.
1130 tracked_objects::ScopedTracker
tracking_profile54(
1131 FROM_HERE_WITH_EXPLICIT_FUNCTION(
1132 "422516 QuicStreamFactory::CreateSession54"));
1134 config
.SetInitialSessionFlowControlWindowToSend(kInitialReceiveWindowSize
);
1136 // TODO(vadimt): Remove ScopedTracker below once crbug.com/422516 is fixed.
1137 tracked_objects::ScopedTracker
tracking_profile55(
1138 FROM_HERE_WITH_EXPLICIT_FUNCTION(
1139 "422516 QuicStreamFactory::CreateSession55"));
1141 int64 srtt
= GetServerNetworkStatsSmoothedRttInMicroseconds(server_id
);
1143 // TODO(vadimt): Remove ScopedTracker below once crbug.com/422516 is fixed.
1144 tracked_objects::ScopedTracker
tracking_profile56(
1145 FROM_HERE_WITH_EXPLICIT_FUNCTION(
1146 "422516 QuicStreamFactory::CreateSession56"));
1149 config
.SetInitialRoundTripTimeUsToSend(static_cast<uint32
>(srtt
));
1151 // TODO(vadimt): Remove ScopedTracker below once crbug.com/422516 is fixed.
1152 tracked_objects::ScopedTracker
tracking_profile57(
1153 FROM_HERE_WITH_EXPLICIT_FUNCTION(
1154 "422516 QuicStreamFactory::CreateSession57"));
1156 if (enable_truncated_connection_ids_
)
1157 config
.SetBytesForConnectionIdToSend(0);
1159 if (quic_server_info_factory_
&& !server_info
) {
1160 // TODO(vadimt): Remove ScopedTracker below once crbug.com/422516 is fixed.
1161 tracked_objects::ScopedTracker
tracking_profile6(
1162 FROM_HERE_WITH_EXPLICIT_FUNCTION(
1163 "422516 QuicStreamFactory::CreateSession6"));
1165 // Start the disk cache loading so that we can persist the newer QUIC server
1166 // information and/or inform the disk cache that we have reused
1168 server_info
.reset(quic_server_info_factory_
->GetForServer(server_id
));
1169 server_info
->Start();
1172 // TODO(vadimt): Remove ScopedTracker below once crbug.com/422516 is fixed.
1173 tracked_objects::ScopedTracker
tracking_profile61(
1174 FROM_HERE_WITH_EXPLICIT_FUNCTION(
1175 "422516 QuicStreamFactory::CreateSession61"));
1177 *session
= new QuicClientSession(
1178 connection
, socket
.Pass(), this, transport_security_state_
,
1179 server_info
.Pass(), config
, network_connection_
.GetDescription(),
1180 dns_resolution_end_time
,
1181 base::MessageLoop::current()->message_loop_proxy().get(),
1184 // TODO(rtenneti): Remove ScopedTracker below once crbug.com/422516 is fixed.
1185 tracked_objects::ScopedTracker
tracking_profile62(
1186 FROM_HERE_WITH_EXPLICIT_FUNCTION(
1187 "422516 QuicStreamFactory::CreateSession62"));
1189 all_sessions_
[*session
] = server_id
; // owning pointer
1191 // TODO(vadimt): Remove ScopedTracker below once crbug.com/422516 is fixed.
1192 tracked_objects::ScopedTracker
tracking_profile7(
1193 FROM_HERE_WITH_EXPLICIT_FUNCTION(
1194 "422516 QuicStreamFactory::CreateSession7"));
1196 (*session
)->InitializeSession(server_id
, &crypto_config_
,
1197 quic_crypto_client_stream_factory_
);
1198 bool closed_during_initialize
=
1199 !ContainsKey(all_sessions_
, *session
) ||
1200 !(*session
)->connection()->connected();
1201 UMA_HISTOGRAM_BOOLEAN("Net.QuicSession.ClosedDuringInitializeSession",
1202 closed_during_initialize
);
1203 if (closed_during_initialize
) {
1204 DLOG(DFATAL
) << "Session closed during initialize";
1206 return ERR_CONNECTION_CLOSED
;
1211 void QuicStreamFactory::ActivateSession(
1212 const QuicServerId
& server_id
,
1213 QuicClientSession
* session
) {
1214 DCHECK(!HasActiveSession(server_id
));
1215 UMA_HISTOGRAM_COUNTS("Net.QuicActiveSessions", active_sessions_
.size());
1216 active_sessions_
[server_id
] = session
;
1217 session_aliases_
[session
].insert(server_id
);
1218 const IpAliasKey
ip_alias_key(session
->connection()->peer_address(),
1219 server_id
.is_https());
1220 DCHECK(!ContainsKey(ip_aliases_
[ip_alias_key
], session
));
1221 ip_aliases_
[ip_alias_key
].insert(session
);
1224 int64
QuicStreamFactory::GetServerNetworkStatsSmoothedRttInMicroseconds(
1225 const QuicServerId
& server_id
) const {
1226 if (!http_server_properties_
)
1228 const ServerNetworkStats
* stats
=
1229 http_server_properties_
->GetServerNetworkStats(
1230 server_id
.host_port_pair());
1231 if (stats
== nullptr)
1233 return stats
->srtt
.InMicroseconds();
1236 bool QuicStreamFactory::WasAlternateProtocolRecentlyBroken(
1237 const QuicServerId
& server_id
) const {
1238 return http_server_properties_
&&
1239 http_server_properties_
->WasAlternateProtocolRecentlyBroken(
1240 server_id
.host_port_pair());
1243 bool QuicStreamFactory::CryptoConfigCacheIsEmpty(
1244 const QuicServerId
& server_id
) {
1245 QuicCryptoClientConfig::CachedState
* cached
=
1246 crypto_config_
.LookupOrCreate(server_id
);
1247 return cached
->IsEmpty();
1250 void QuicStreamFactory::InitializeCachedStateInCryptoConfig(
1251 const QuicServerId
& server_id
,
1252 const scoped_ptr
<QuicServerInfo
>& server_info
) {
1253 // TODO(vadimt): Remove ScopedTracker below once crbug.com/422516 is fixed.
1254 tracked_objects::ScopedTracker
tracking_profile1(
1255 FROM_HERE_WITH_EXPLICIT_FUNCTION(
1256 "422516 QuicStreamFactory::InitializeCachedStateInCryptoConfig1"));
1258 // |server_info| will be NULL, if a non-empty server config already exists in
1259 // the memory cache. This is a minor optimization to avoid LookupOrCreate.
1263 QuicCryptoClientConfig::CachedState
* cached
=
1264 crypto_config_
.LookupOrCreate(server_id
);
1265 if (!cached
->IsEmpty())
1268 if (http_server_properties_
) {
1269 if (quic_supported_servers_at_startup_
.empty()) {
1270 for (const std::pair
<const HostPortPair
, AlternateProtocolInfo
>&
1271 key_value
: http_server_properties_
->alternate_protocol_map()) {
1272 if (key_value
.second
.protocol
== QUIC
) {
1273 quic_supported_servers_at_startup_
.insert(key_value
.first
);
1278 // TODO(rtenneti): Delete the following histogram after collecting stats.
1279 // If the AlternateProtocolMap contained an entry for this host, check if
1280 // the disk cache contained an entry for it.
1281 if (ContainsKey(quic_supported_servers_at_startup_
,
1282 server_id
.host_port_pair())) {
1283 UMA_HISTOGRAM_BOOLEAN(
1284 "Net.QuicServerInfo.ExpectConfigMissingFromDiskCache",
1285 server_info
->state().server_config
.empty());
1289 // TODO(vadimt): Remove ScopedTracker below once crbug.com/422516 is fixed.
1290 tracked_objects::ScopedTracker
tracking_profile2(
1291 FROM_HERE_WITH_EXPLICIT_FUNCTION(
1292 "422516 QuicStreamFactory::InitializeCachedStateInCryptoConfig2"));
1294 if (!cached
->Initialize(server_info
->state().server_config
,
1295 server_info
->state().source_address_token
,
1296 server_info
->state().certs
,
1297 server_info
->state().server_config_sig
,
1301 if (!server_id
.is_https()) {
1302 // Don't check the certificates for insecure QUIC.
1303 cached
->SetProofValid();
1307 void QuicStreamFactory::ProcessGoingAwaySession(
1308 QuicClientSession
* session
,
1309 const QuicServerId
& server_id
,
1310 bool session_was_active
) {
1311 if (!http_server_properties_
)
1314 const QuicConnectionStats
& stats
= session
->connection()->GetStats();
1315 if (session
->IsCryptoHandshakeConfirmed()) {
1316 ServerNetworkStats network_stats
;
1317 network_stats
.srtt
= base::TimeDelta::FromMicroseconds(stats
.srtt_us
);
1318 network_stats
.bandwidth_estimate
= stats
.estimated_bandwidth
;
1319 http_server_properties_
->SetServerNetworkStats(server_id
.host_port_pair(),
1324 UMA_HISTOGRAM_COUNTS("Net.QuicHandshakeNotConfirmedNumPacketsReceived",
1325 stats
.packets_received
);
1327 if (!session_was_active
)
1330 const HostPortPair
& server
= server_id
.host_port_pair();
1331 // Don't try to change the alternate-protocol state, if the
1332 // alternate-protocol state is unknown.
1333 const AlternateProtocolInfo alternate
=
1334 http_server_properties_
->GetAlternateProtocol(server
);
1335 if (alternate
.protocol
== UNINITIALIZED_ALTERNATE_PROTOCOL
)
1338 // TODO(rch): In the special case where the session has received no
1339 // packets from the peer, we should consider blacklisting this
1340 // differently so that we still race TCP but we don't consider the
1341 // session connected until the handshake has been confirmed.
1342 HistogramBrokenAlternateProtocolLocation(
1343 BROKEN_ALTERNATE_PROTOCOL_LOCATION_QUIC_STREAM_FACTORY
);
1344 DCHECK_EQ(QUIC
, alternate
.protocol
);
1346 // Since the session was active, there's no longer an
1347 // HttpStreamFactoryImpl::Job running which can mark it broken, unless the
1348 // TCP job also fails. So to avoid not using QUIC when we otherwise could,
1349 // we mark it as broken, and then immediately re-enable it. This leaves
1350 // QUIC as "recently broken" which means that 0-RTT will be disabled but
1351 // we'll still race.
1352 http_server_properties_
->SetBrokenAlternateProtocol(server
);
1353 http_server_properties_
->ClearAlternateProtocol(server
);
1354 http_server_properties_
->SetAlternateProtocol(
1355 server
, alternate
.port
, alternate
.protocol
, 1);
1357 http_server_properties_
->GetAlternateProtocol(server
).protocol
);
1358 DCHECK(http_server_properties_
->WasAlternateProtocolRecentlyBroken(