| OLD | NEW |
| 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 <algorithm> | 7 #include <algorithm> |
| 8 #include <set> | 8 #include <set> |
| 9 | 9 |
| 10 #include "base/location.h" | 10 #include "base/location.h" |
| 11 #include "base/macros.h" |
| 11 #include "base/metrics/field_trial.h" | 12 #include "base/metrics/field_trial.h" |
| 12 #include "base/metrics/histogram_macros.h" | 13 #include "base/metrics/histogram_macros.h" |
| 13 #include "base/metrics/sparse_histogram.h" | 14 #include "base/metrics/sparse_histogram.h" |
| 14 #include "base/rand_util.h" | 15 #include "base/rand_util.h" |
| 15 #include "base/single_thread_task_runner.h" | 16 #include "base/single_thread_task_runner.h" |
| 16 #include "base/stl_util.h" | 17 #include "base/stl_util.h" |
| 17 #include "base/strings/string_util.h" | 18 #include "base/strings/string_util.h" |
| 18 #include "base/strings/stringprintf.h" | 19 #include "base/strings/stringprintf.h" |
| 19 #include "base/thread_task_runner_handle.h" | 20 #include "base/thread_task_runner_handle.h" |
| 20 #include "base/values.h" | 21 #include "base/values.h" |
| (...skipping 43 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 64 namespace { | 65 namespace { |
| 65 | 66 |
| 66 enum CreateSessionFailure { | 67 enum CreateSessionFailure { |
| 67 CREATION_ERROR_CONNECTING_SOCKET, | 68 CREATION_ERROR_CONNECTING_SOCKET, |
| 68 CREATION_ERROR_SETTING_RECEIVE_BUFFER, | 69 CREATION_ERROR_SETTING_RECEIVE_BUFFER, |
| 69 CREATION_ERROR_SETTING_SEND_BUFFER, | 70 CREATION_ERROR_SETTING_SEND_BUFFER, |
| 70 CREATION_ERROR_MAX | 71 CREATION_ERROR_MAX |
| 71 }; | 72 }; |
| 72 | 73 |
| 73 // The maximum receive window sizes for QUIC sessions and streams. | 74 // The maximum receive window sizes for QUIC sessions and streams. |
| 74 const int32 kQuicSessionMaxRecvWindowSize = 15 * 1024 * 1024; // 15 MB | 75 const int32_t kQuicSessionMaxRecvWindowSize = 15 * 1024 * 1024; // 15 MB |
| 75 const int32 kQuicStreamMaxRecvWindowSize = 6 * 1024 * 1024; // 6 MB | 76 const int32_t kQuicStreamMaxRecvWindowSize = 6 * 1024 * 1024; // 6 MB |
| 76 | 77 |
| 77 // Set the maximum number of undecryptable packets the connection will store. | 78 // Set the maximum number of undecryptable packets the connection will store. |
| 78 const int32 kMaxUndecryptablePackets = 100; | 79 const int32_t kMaxUndecryptablePackets = 100; |
| 79 | 80 |
| 80 void HistogramCreateSessionFailure(enum CreateSessionFailure error) { | 81 void HistogramCreateSessionFailure(enum CreateSessionFailure error) { |
| 81 UMA_HISTOGRAM_ENUMERATION("Net.QuicSession.CreationError", error, | 82 UMA_HISTOGRAM_ENUMERATION("Net.QuicSession.CreationError", error, |
| 82 CREATION_ERROR_MAX); | 83 CREATION_ERROR_MAX); |
| 83 } | 84 } |
| 84 | 85 |
| 85 bool IsEcdsaSupported() { | 86 bool IsEcdsaSupported() { |
| 86 #if defined(OS_WIN) | 87 #if defined(OS_WIN) |
| 87 if (base::win::GetVersion() < base::win::VERSION_VISTA) | 88 if (base::win::GetVersion() < base::win::VERSION_VISTA) |
| 88 return false; | 89 return false; |
| (...skipping 277 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 366 int QuicStreamFactory::Job::DoLoadServerInfo() { | 367 int QuicStreamFactory::Job::DoLoadServerInfo() { |
| 367 io_state_ = STATE_LOAD_SERVER_INFO_COMPLETE; | 368 io_state_ = STATE_LOAD_SERVER_INFO_COMPLETE; |
| 368 | 369 |
| 369 DCHECK(server_info_); | 370 DCHECK(server_info_); |
| 370 | 371 |
| 371 // To mitigate the effects of disk cache taking too long to load QUIC server | 372 // To mitigate the effects of disk cache taking too long to load QUIC server |
| 372 // information, set up a timer to cancel WaitForDataReady's callback. | 373 // information, set up a timer to cancel WaitForDataReady's callback. |
| 373 if (factory_->load_server_info_timeout_srtt_multiplier_ > 0) { | 374 if (factory_->load_server_info_timeout_srtt_multiplier_ > 0) { |
| 374 const int kMaxLoadServerInfoTimeoutMs = 50; | 375 const int kMaxLoadServerInfoTimeoutMs = 50; |
| 375 // Wait for DiskCache a maximum of 50ms. | 376 // Wait for DiskCache a maximum of 50ms. |
| 376 int64 load_server_info_timeout_ms = | 377 int64_t load_server_info_timeout_ms = |
| 377 min(static_cast<int>( | 378 min(static_cast<int>( |
| 378 (factory_->load_server_info_timeout_srtt_multiplier_ * | 379 (factory_->load_server_info_timeout_srtt_multiplier_ * |
| 379 factory_->GetServerNetworkStatsSmoothedRttInMicroseconds( | 380 factory_->GetServerNetworkStatsSmoothedRttInMicroseconds( |
| 380 server_id_)) / | 381 server_id_)) / |
| 381 1000), | 382 1000), |
| 382 kMaxLoadServerInfoTimeoutMs); | 383 kMaxLoadServerInfoTimeoutMs); |
| 383 if (load_server_info_timeout_ms > 0) { | 384 if (load_server_info_timeout_ms > 0) { |
| 384 factory_->task_runner_->PostDelayedTask( | 385 factory_->task_runner_->PostDelayedTask( |
| 385 FROM_HERE, | 386 FROM_HERE, |
| 386 base::Bind(&QuicStreamFactory::Job::CancelWaitForDataReadyCallback, | 387 base::Bind(&QuicStreamFactory::Job::CancelWaitForDataReadyCallback, |
| (...skipping 299 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 686 } | 687 } |
| 687 | 688 |
| 688 bool QuicStreamFactory::ZeroRTTEnabledFor(const QuicServerId& quic_server_id) { | 689 bool QuicStreamFactory::ZeroRTTEnabledFor(const QuicServerId& quic_server_id) { |
| 689 return !(require_confirmation_ || CryptoConfigCacheIsEmpty(quic_server_id)); | 690 return !(require_confirmation_ || CryptoConfigCacheIsEmpty(quic_server_id)); |
| 690 } | 691 } |
| 691 | 692 |
| 692 base::TimeDelta QuicStreamFactory::GetTimeDelayForWaitingJob( | 693 base::TimeDelta QuicStreamFactory::GetTimeDelayForWaitingJob( |
| 693 const QuicServerId& server_id) { | 694 const QuicServerId& server_id) { |
| 694 if (!delay_tcp_race_ || require_confirmation_) | 695 if (!delay_tcp_race_ || require_confirmation_) |
| 695 return base::TimeDelta(); | 696 return base::TimeDelta(); |
| 696 int64 srtt = 1.5 * GetServerNetworkStatsSmoothedRttInMicroseconds(server_id); | 697 int64_t srtt = |
| 698 1.5 * GetServerNetworkStatsSmoothedRttInMicroseconds(server_id); |
| 697 // Picked 300ms based on mean time from | 699 // Picked 300ms based on mean time from |
| 698 // Net.QuicSession.HostResolution.HandshakeConfirmedTime histogram. | 700 // Net.QuicSession.HostResolution.HandshakeConfirmedTime histogram. |
| 699 const int kDefaultRTT = 300 * kNumMicrosPerMilli; | 701 const int kDefaultRTT = 300 * kNumMicrosPerMilli; |
| 700 if (!srtt) | 702 if (!srtt) |
| 701 srtt = kDefaultRTT; | 703 srtt = kDefaultRTT; |
| 702 return base::TimeDelta::FromMicroseconds(srtt); | 704 return base::TimeDelta::FromMicroseconds(srtt); |
| 703 } | 705 } |
| 704 | 706 |
| 705 void QuicStreamFactory::set_quic_server_info_factory( | 707 void QuicStreamFactory::set_quic_server_info_factory( |
| 706 QuicServerInfoFactory* quic_server_info_factory) { | 708 QuicServerInfoFactory* quic_server_info_factory) { |
| (...skipping 174 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 881 active_jobs_.erase(server_id); | 883 active_jobs_.erase(server_id); |
| 882 job_requests_map_.erase(server_id); | 884 job_requests_map_.erase(server_id); |
| 883 } | 885 } |
| 884 | 886 |
| 885 scoped_ptr<QuicHttpStream> QuicStreamFactory::CreateFromSession( | 887 scoped_ptr<QuicHttpStream> QuicStreamFactory::CreateFromSession( |
| 886 QuicChromiumClientSession* session) { | 888 QuicChromiumClientSession* session) { |
| 887 return scoped_ptr<QuicHttpStream>(new QuicHttpStream(session->GetWeakPtr())); | 889 return scoped_ptr<QuicHttpStream>(new QuicHttpStream(session->GetWeakPtr())); |
| 888 } | 890 } |
| 889 | 891 |
| 890 QuicChromiumClientSession::QuicDisabledReason | 892 QuicChromiumClientSession::QuicDisabledReason |
| 891 QuicStreamFactory::QuicDisabledReason(uint16 port) const { | 893 QuicStreamFactory::QuicDisabledReason(uint16_t port) const { |
| 892 if (max_number_of_lossy_connections_ > 0 && | 894 if (max_number_of_lossy_connections_ > 0 && |
| 893 number_of_lossy_connections_.find(port) != | 895 number_of_lossy_connections_.find(port) != |
| 894 number_of_lossy_connections_.end() && | 896 number_of_lossy_connections_.end() && |
| 895 number_of_lossy_connections_.at(port) >= | 897 number_of_lossy_connections_.at(port) >= |
| 896 max_number_of_lossy_connections_) { | 898 max_number_of_lossy_connections_) { |
| 897 return QuicChromiumClientSession::QUIC_DISABLED_BAD_PACKET_LOSS_RATE; | 899 return QuicChromiumClientSession::QUIC_DISABLED_BAD_PACKET_LOSS_RATE; |
| 898 } | 900 } |
| 899 if (threshold_public_resets_post_handshake_ > 0 && | 901 if (threshold_public_resets_post_handshake_ > 0 && |
| 900 num_public_resets_post_handshake_ >= | 902 num_public_resets_post_handshake_ >= |
| 901 threshold_public_resets_post_handshake_) { | 903 threshold_public_resets_post_handshake_) { |
| 902 return QuicChromiumClientSession::QUIC_DISABLED_PUBLIC_RESET_POST_HANDSHAKE; | 904 return QuicChromiumClientSession::QUIC_DISABLED_PUBLIC_RESET_POST_HANDSHAKE; |
| 903 } | 905 } |
| 904 if (threshold_timeouts_with_open_streams_ > 0 && | 906 if (threshold_timeouts_with_open_streams_ > 0 && |
| 905 num_timeouts_with_open_streams_ >= | 907 num_timeouts_with_open_streams_ >= |
| 906 threshold_timeouts_with_open_streams_) { | 908 threshold_timeouts_with_open_streams_) { |
| 907 return QuicChromiumClientSession::QUIC_DISABLED_TIMEOUT_WITH_OPEN_STREAMS; | 909 return QuicChromiumClientSession::QUIC_DISABLED_TIMEOUT_WITH_OPEN_STREAMS; |
| 908 } | 910 } |
| 909 return QuicChromiumClientSession::QUIC_DISABLED_NOT; | 911 return QuicChromiumClientSession::QUIC_DISABLED_NOT; |
| 910 } | 912 } |
| 911 | 913 |
| 912 const char* QuicStreamFactory::QuicDisabledReasonString() const { | 914 const char* QuicStreamFactory::QuicDisabledReasonString() const { |
| 913 // TODO(ckrasic) - better solution for port/lossy connections? | 915 // TODO(ckrasic) - better solution for port/lossy connections? |
| 914 const uint16 port = 443; | 916 const uint16_t port = 443; |
| 915 switch (QuicDisabledReason(port)) { | 917 switch (QuicDisabledReason(port)) { |
| 916 case QuicChromiumClientSession::QUIC_DISABLED_BAD_PACKET_LOSS_RATE: | 918 case QuicChromiumClientSession::QUIC_DISABLED_BAD_PACKET_LOSS_RATE: |
| 917 return "Bad packet loss rate."; | 919 return "Bad packet loss rate."; |
| 918 case QuicChromiumClientSession::QUIC_DISABLED_PUBLIC_RESET_POST_HANDSHAKE: | 920 case QuicChromiumClientSession::QUIC_DISABLED_PUBLIC_RESET_POST_HANDSHAKE: |
| 919 return "Public resets after successful handshakes."; | 921 return "Public resets after successful handshakes."; |
| 920 case QuicChromiumClientSession::QUIC_DISABLED_TIMEOUT_WITH_OPEN_STREAMS: | 922 case QuicChromiumClientSession::QUIC_DISABLED_TIMEOUT_WITH_OPEN_STREAMS: |
| 921 return "Connection timeouts with streams open."; | 923 return "Connection timeouts with streams open."; |
| 922 default: | 924 default: |
| 923 return ""; | 925 return ""; |
| 924 } | 926 } |
| 925 } | 927 } |
| 926 | 928 |
| 927 bool QuicStreamFactory::IsQuicDisabled(uint16 port) { | 929 bool QuicStreamFactory::IsQuicDisabled(uint16_t port) { |
| 928 return QuicDisabledReason(port) != | 930 return QuicDisabledReason(port) != |
| 929 QuicChromiumClientSession::QUIC_DISABLED_NOT; | 931 QuicChromiumClientSession::QUIC_DISABLED_NOT; |
| 930 } | 932 } |
| 931 | 933 |
| 932 bool QuicStreamFactory::OnHandshakeConfirmed(QuicChromiumClientSession* session, | 934 bool QuicStreamFactory::OnHandshakeConfirmed(QuicChromiumClientSession* session, |
| 933 float packet_loss_rate) { | 935 float packet_loss_rate) { |
| 934 DCHECK(session); | 936 DCHECK(session); |
| 935 uint16 port = session->server_id().port(); | 937 uint16_t port = session->server_id().port(); |
| 936 if (packet_loss_rate < packet_loss_threshold_) { | 938 if (packet_loss_rate < packet_loss_threshold_) { |
| 937 number_of_lossy_connections_[port] = 0; | 939 number_of_lossy_connections_[port] = 0; |
| 938 return false; | 940 return false; |
| 939 } | 941 } |
| 940 | 942 |
| 941 // We mark it as recently broken, which means that 0-RTT will be disabled | 943 // We mark it as recently broken, which means that 0-RTT will be disabled |
| 942 // but we'll still race. | 944 // but we'll still race. |
| 943 http_server_properties_->MarkAlternativeServiceRecentlyBroken( | 945 http_server_properties_->MarkAlternativeServiceRecentlyBroken( |
| 944 AlternativeService(QUIC, session->server_id().host(), port)); | 946 AlternativeService(QUIC, session->server_id().host(), port)); |
| 945 | 947 |
| (...skipping 45 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 991 ip_aliases_[peer_address].erase(session); | 993 ip_aliases_[peer_address].erase(session); |
| 992 if (ip_aliases_[peer_address].empty()) { | 994 if (ip_aliases_[peer_address].empty()) { |
| 993 ip_aliases_.erase(peer_address); | 995 ip_aliases_.erase(peer_address); |
| 994 } | 996 } |
| 995 } | 997 } |
| 996 session_aliases_.erase(session); | 998 session_aliases_.erase(session); |
| 997 } | 999 } |
| 998 | 1000 |
| 999 void QuicStreamFactory::MaybeDisableQuic(QuicChromiumClientSession* session) { | 1001 void QuicStreamFactory::MaybeDisableQuic(QuicChromiumClientSession* session) { |
| 1000 DCHECK(session); | 1002 DCHECK(session); |
| 1001 uint16 port = session->server_id().port(); | 1003 uint16_t port = session->server_id().port(); |
| 1002 if (IsQuicDisabled(port)) | 1004 if (IsQuicDisabled(port)) |
| 1003 return; | 1005 return; |
| 1004 | 1006 |
| 1005 // Expire the oldest disabled_reason if appropriate. This enforces that we | 1007 // Expire the oldest disabled_reason if appropriate. This enforces that we |
| 1006 // only consider the max_disabled_reasons_ most recent sessions. | 1008 // only consider the max_disabled_reasons_ most recent sessions. |
| 1007 QuicChromiumClientSession::QuicDisabledReason disabled_reason; | 1009 QuicChromiumClientSession::QuicDisabledReason disabled_reason; |
| 1008 if (static_cast<int>(disabled_reasons_.size()) == max_disabled_reasons_) { | 1010 if (static_cast<int>(disabled_reasons_.size()) == max_disabled_reasons_) { |
| 1009 disabled_reason = disabled_reasons_.front(); | 1011 disabled_reason = disabled_reasons_.front(); |
| 1010 disabled_reasons_.pop_front(); | 1012 disabled_reasons_.pop_front(); |
| 1011 if (disabled_reason == | 1013 if (disabled_reason == |
| (...skipping 252 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1264 connection->SetMaxPacketLength(max_packet_length_); | 1266 connection->SetMaxPacketLength(max_packet_length_); |
| 1265 | 1267 |
| 1266 InitializeCachedStateInCryptoConfig(server_id, server_info); | 1268 InitializeCachedStateInCryptoConfig(server_id, server_info); |
| 1267 | 1269 |
| 1268 QuicConfig config = config_; | 1270 QuicConfig config = config_; |
| 1269 config.SetSocketReceiveBufferToSend(socket_receive_buffer_size_); | 1271 config.SetSocketReceiveBufferToSend(socket_receive_buffer_size_); |
| 1270 config.set_max_undecryptable_packets(kMaxUndecryptablePackets); | 1272 config.set_max_undecryptable_packets(kMaxUndecryptablePackets); |
| 1271 config.SetInitialSessionFlowControlWindowToSend( | 1273 config.SetInitialSessionFlowControlWindowToSend( |
| 1272 kQuicSessionMaxRecvWindowSize); | 1274 kQuicSessionMaxRecvWindowSize); |
| 1273 config.SetInitialStreamFlowControlWindowToSend(kQuicStreamMaxRecvWindowSize); | 1275 config.SetInitialStreamFlowControlWindowToSend(kQuicStreamMaxRecvWindowSize); |
| 1274 int64 srtt = GetServerNetworkStatsSmoothedRttInMicroseconds(server_id); | 1276 int64_t srtt = GetServerNetworkStatsSmoothedRttInMicroseconds(server_id); |
| 1275 if (srtt > 0) | 1277 if (srtt > 0) |
| 1276 config.SetInitialRoundTripTimeUsToSend(static_cast<uint32>(srtt)); | 1278 config.SetInitialRoundTripTimeUsToSend(static_cast<uint32_t>(srtt)); |
| 1277 config.SetBytesForConnectionIdToSend(0); | 1279 config.SetBytesForConnectionIdToSend(0); |
| 1278 | 1280 |
| 1279 if (quic_server_info_factory_.get() && !server_info) { | 1281 if (quic_server_info_factory_.get() && !server_info) { |
| 1280 // Start the disk cache loading so that we can persist the newer QUIC server | 1282 // Start the disk cache loading so that we can persist the newer QUIC server |
| 1281 // information and/or inform the disk cache that we have reused | 1283 // information and/or inform the disk cache that we have reused |
| 1282 // |server_info|. | 1284 // |server_info|. |
| 1283 server_info.reset(quic_server_info_factory_->GetForServer(server_id)); | 1285 server_info.reset(quic_server_info_factory_->GetForServer(server_id)); |
| 1284 server_info->Start(); | 1286 server_info->Start(); |
| 1285 } | 1287 } |
| 1286 | 1288 |
| (...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1320 QuicChromiumClientSession* session) { | 1322 QuicChromiumClientSession* session) { |
| 1321 DCHECK(!HasActiveSession(server_id)); | 1323 DCHECK(!HasActiveSession(server_id)); |
| 1322 UMA_HISTOGRAM_COUNTS("Net.QuicActiveSessions", active_sessions_.size()); | 1324 UMA_HISTOGRAM_COUNTS("Net.QuicActiveSessions", active_sessions_.size()); |
| 1323 active_sessions_[server_id] = session; | 1325 active_sessions_[server_id] = session; |
| 1324 session_aliases_[session].insert(server_id); | 1326 session_aliases_[session].insert(server_id); |
| 1325 const IPEndPoint peer_address = session->connection()->peer_address(); | 1327 const IPEndPoint peer_address = session->connection()->peer_address(); |
| 1326 DCHECK(!ContainsKey(ip_aliases_[peer_address], session)); | 1328 DCHECK(!ContainsKey(ip_aliases_[peer_address], session)); |
| 1327 ip_aliases_[peer_address].insert(session); | 1329 ip_aliases_[peer_address].insert(session); |
| 1328 } | 1330 } |
| 1329 | 1331 |
| 1330 int64 QuicStreamFactory::GetServerNetworkStatsSmoothedRttInMicroseconds( | 1332 int64_t QuicStreamFactory::GetServerNetworkStatsSmoothedRttInMicroseconds( |
| 1331 const QuicServerId& server_id) const { | 1333 const QuicServerId& server_id) const { |
| 1332 const ServerNetworkStats* stats = | 1334 const ServerNetworkStats* stats = |
| 1333 http_server_properties_->GetServerNetworkStats( | 1335 http_server_properties_->GetServerNetworkStats( |
| 1334 server_id.host_port_pair()); | 1336 server_id.host_port_pair()); |
| 1335 if (stats == nullptr) | 1337 if (stats == nullptr) |
| 1336 return 0; | 1338 return 0; |
| 1337 return stats->srtt.InMicroseconds(); | 1339 return stats->srtt.InMicroseconds(); |
| 1338 } | 1340 } |
| 1339 | 1341 |
| 1340 bool QuicStreamFactory::WasQuicRecentlyBroken( | 1342 bool QuicStreamFactory::WasQuicRecentlyBroken( |
| (...skipping 112 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1453 // Since the session was active, there's no longer an | 1455 // Since the session was active, there's no longer an |
| 1454 // HttpStreamFactoryImpl::Job running which can mark it broken, unless the TCP | 1456 // HttpStreamFactoryImpl::Job running which can mark it broken, unless the TCP |
| 1455 // job also fails. So to avoid not using QUIC when we otherwise could, we mark | 1457 // job also fails. So to avoid not using QUIC when we otherwise could, we mark |
| 1456 // it as recently broken, which means that 0-RTT will be disabled but we'll | 1458 // it as recently broken, which means that 0-RTT will be disabled but we'll |
| 1457 // still race. | 1459 // still race. |
| 1458 http_server_properties_->MarkAlternativeServiceRecentlyBroken( | 1460 http_server_properties_->MarkAlternativeServiceRecentlyBroken( |
| 1459 alternative_service); | 1461 alternative_service); |
| 1460 } | 1462 } |
| 1461 | 1463 |
| 1462 } // namespace net | 1464 } // namespace net |
| OLD | NEW |