const int32 kServerSecureInitialCongestionWindow = 32;
// Be conservative, and just use double a typical TCP ICWND for HTTP.
const int32 kServerInecureInitialCongestionWindow = 20;
+// Set the maximum number of undecryptable packets the connection will store.
+const int32 kMaxUndecryptablePackets = 100;
const char kDummyHostname[] = "quic.global.props";
const uint16 kDummyPort = 0;
return true;
}
-QuicConfig InitializeQuicConfig(bool enable_time_based_loss_detection,
- const QuicTagVector& connection_options) {
+QuicConfig InitializeQuicConfig(const QuicTagVector& connection_options) {
QuicConfig config;
- config.SetDefaults();
- if (enable_time_based_loss_detection)
- config.SetLossDetectionToSend(kTIME);
- config.set_idle_connection_state_lifetime(
+ config.SetIdleConnectionStateLifetime(
QuicTime::Delta::FromSeconds(kIdleConnectionTimeoutSeconds),
QuicTime::Delta::FromSeconds(kIdleConnectionTimeoutSeconds));
config.SetConnectionOptionsToSend(connection_options);
public:
explicit DefaultPacketWriterFactory(DatagramClientSocket* socket)
: socket_(socket) {}
- virtual ~DefaultPacketWriterFactory() {}
+ ~DefaultPacketWriterFactory() override {}
- virtual QuicPacketWriter* Create(QuicConnection* connection) const OVERRIDE;
+ QuicPacketWriter* Create(QuicConnection* connection) const override;
private:
DatagramClientSocket* socket_;
void OnIOComplete(int rv);
+ void CancelWaitForDataReadyCallback();
+
CompletionCallback callback() {
return callback_;
}
was_alternate_protocol_recently_broken),
server_info_(server_info),
net_log_(net_log),
- session_(NULL),
+ session_(nullptr),
weak_factory_(this) {}
QuicStreamFactory::Job::Job(QuicStreamFactory* factory,
}
}
+void QuicStreamFactory::Job::CancelWaitForDataReadyCallback() {
+ // If we are waiting for WaitForDataReadyCallback, then cancel the callback.
+ if (io_state_ != STATE_LOAD_SERVER_INFO_COMPLETE)
+ return;
+ server_info_->CancelWaitForDataReadyCallback();
+ OnIOComplete(OK);
+}
+
int QuicStreamFactory::Job::DoResolveHost() {
// Start loading the data now, and wait for it after we resolve the host.
if (server_info_) {
- disk_cache_load_start_time_ = base::TimeTicks::Now();
server_info_->Start();
}
if (!server_info_)
return OK;
+ // To mitigate the effects of disk cache taking too long to load QUIC server
+ // information, set up a timer to cancel WaitForDataReady's callback.
+ if (factory_->load_server_info_timeout_ms_ > 0) {
+ factory_->task_runner_->PostDelayedTask(
+ FROM_HERE,
+ base::Bind(&QuicStreamFactory::Job::CancelWaitForDataReadyCallback,
+ weak_factory_.GetWeakPtr()),
+ base::TimeDelta::FromMilliseconds(
+ factory_->load_server_info_timeout_ms_));
+ }
+
+ disk_cache_load_start_time_ = base::TimeTicks::Now();
return server_info_->WaitForDataReady(
base::Bind(&QuicStreamFactory::Job::OnIOComplete,
weak_factory_.GetWeakPtr()));
int QuicStreamFactory::Job::DoLoadServerInfoComplete(int rv) {
if (server_info_) {
- UMA_HISTOGRAM_TIMES("Net.QuicServerInfo.DiskCacheReadTime",
+ UMA_HISTOGRAM_TIMES("Net.QuicServerInfo.DiskCacheWaitForDataReadyTime",
base::TimeTicks::Now() - disk_cache_load_start_time_);
}
AddressList address(session_->connection()->peer_address());
if (factory_->OnResolution(server_id_, address)) {
session_->connection()->SendConnectionClose(QUIC_CONNECTION_IP_POOLED);
- session_ = NULL;
+ session_ = nullptr;
return OK;
}
net_log_ = net_log;
callback_ = callback;
} else {
- factory_ = NULL;
+ factory_ = nullptr;
}
if (rv == OK)
DCHECK(stream_);
}
void QuicStreamRequest::OnRequestComplete(int rv) {
- factory_ = NULL;
+ factory_ = nullptr;
callback_.Run(rv);
}
const std::string& user_agent_id,
const QuicVersionVector& supported_versions,
bool enable_port_selection,
- bool enable_time_based_loss_detection,
bool always_require_handshake_confirmation,
bool disable_connection_pooling,
+ int load_server_info_timeout,
const QuicTagVector& connection_options)
: require_confirmation_(true),
host_resolver_(host_resolver),
client_socket_factory_(client_socket_factory),
http_server_properties_(http_server_properties),
transport_security_state_(transport_security_state),
- quic_server_info_factory_(NULL),
+ quic_server_info_factory_(nullptr),
quic_crypto_client_stream_factory_(quic_crypto_client_stream_factory),
random_generator_(random_generator),
clock_(clock),
max_packet_length_(max_packet_length),
- config_(InitializeQuicConfig(enable_time_based_loss_detection,
- connection_options)),
+ config_(InitializeQuicConfig(connection_options)),
supported_versions_(supported_versions),
enable_port_selection_(enable_port_selection),
always_require_handshake_confirmation_(
always_require_handshake_confirmation),
disable_connection_pooling_(disable_connection_pooling),
+ load_server_info_timeout_ms_(load_server_info_timeout),
port_seed_(random_generator_->RandUint64()),
check_persisted_supports_quic_(true),
+ task_runner_(nullptr),
weak_factory_(this) {
DCHECK(transport_security_state_);
- crypto_config_.SetDefaults();
crypto_config_.set_user_agent_id(user_agent_id);
crypto_config_.AddCanonicalSuffix(".c.youtube.com");
crypto_config_.AddCanonicalSuffix(".googlevideo.com");
return ERR_IO_PENDING;
}
- QuicServerInfo* quic_server_info = NULL;
+ QuicServerInfo* quic_server_info = nullptr;
if (quic_server_info_factory_) {
QuicCryptoClientConfig::CachedState* cached =
crypto_config_.LookupOrCreate(server_id);
quic_server_info = quic_server_info_factory_->GetForServer(server_id);
}
}
+ // TODO(rtenneti): Initialize task_runner_ in the constructor after
+ // WebRequestActionWithThreadsTest.* tests are fixed.
+ if (!task_runner_)
+ task_runner_ = base::MessageLoop::current()->message_loop_proxy().get();
+
bool was_alternate_protocol_recently_broken =
http_server_properties_ &&
http_server_properties_->WasAlternateProtocolRecentlyBroken(
}
// Returns a newly created QuicHttpStream owned by the caller, if a
-// matching session already exists. Returns NULL otherwise.
+// matching session already exists. Returns nullptr otherwise.
scoped_ptr<QuicHttpStream> QuicStreamFactory::CreateIfSessionExists(
const QuicServerId& server_id,
const BoundNetLog& net_log) {
config.SetInitialCongestionWindowToSend(
server_id.is_https() ? kServerSecureInitialCongestionWindow
: kServerInecureInitialCongestionWindow);
+ config.set_max_undecryptable_packets(kMaxUndecryptablePackets);
config.SetInitialFlowControlWindowToSend(kInitialReceiveWindowSize);
config.SetInitialStreamFlowControlWindowToSend(kInitialReceiveWindowSize);
config.SetInitialSessionFlowControlWindowToSend(kInitialReceiveWindowSize);
const HttpServerProperties::NetworkStats* stats =
http_server_properties_->GetServerNetworkStats(
server_id.host_port_pair());
- if (stats != NULL) {
+ if (stats != nullptr) {
config.SetInitialRoundTripTimeUsToSend(stats->srtt.InMicroseconds());
}
}
+ if (quic_server_info_factory_ && !server_info) {
+ // Start the disk cache loading so that we can persist the newer QUIC server
+ // information and/or inform the disk cache that we have reused
+ // |server_info|.
+ server_info.reset(quic_server_info_factory_->GetForServer(server_id));
+ server_info->Start();
+ }
+
*session = new QuicClientSession(
connection, socket.Pass(), this, transport_security_state_,
- server_info.Pass(), config,
+ server_info.Pass(), config, server_id.is_https(),
base::MessageLoop::current()->message_loop_proxy().get(),
net_log.net_log());
all_sessions_[*session] = server_id; // owning pointer
closed_during_initialize);
if (closed_during_initialize) {
DLOG(DFATAL) << "Session closed during initialize";
- *session = NULL;
+ *session = nullptr;
return ERR_CONNECTION_CLOSED;
}
return OK;
void QuicStreamFactory::InitializeCachedStateInCryptoConfig(
const QuicServerId& server_id,
const scoped_ptr<QuicServerInfo>& server_info) {
+ // |server_info| will be NULL, if a non-empty server config already exists in
+ // the memory cache. This is a minor optimization to avoid LookupOrCreate.
if (!server_info)
return;
if (!cached->IsEmpty())
return;
+ if (http_server_properties_) {
+ if (quic_supported_servers_at_startup_.empty()) {
+ for (const std::pair<net::HostPortPair, net::AlternateProtocolInfo>&
+ key_value : http_server_properties_->alternate_protocol_map()) {
+ if (key_value.second.protocol == QUIC) {
+ quic_supported_servers_at_startup_.insert(key_value.first);
+ }
+ }
+ }
+
+ // TODO(rtenneti): Delete the following histogram after collecting stats.
+ // If the AlternateProtocolMap contained an entry for this host, check if
+ // the disk cache contained an entry for it.
+ if (ContainsKey(quic_supported_servers_at_startup_,
+ server_id.host_port_pair())) {
+ UMA_HISTOGRAM_BOOLEAN(
+ "Net.QuicServerInfo.ExpectConfigMissingFromDiskCache",
+ server_info->state().server_config.empty());
+ }
+ }
+
if (!cached->Initialize(server_info->state().server_config,
server_info->state().source_address_token,
server_info->state().certs,