Update To 11.40.268.0
[platform/framework/web/crosswalk.git] / src / net / quic / quic_stream_factory.cc
index c7aeb4c..076797a 100644 (file)
@@ -70,6 +70,8 @@ const int32 kInitialReceiveWindowSize = 10 * 1024 * 1024;  // 10MB
 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;
@@ -88,13 +90,9 @@ bool IsEcdsaSupported() {
   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);
@@ -105,9 +103,9 @@ class DefaultPacketWriterFactory : public QuicConnection::PacketWriterFactory {
  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_;
@@ -182,6 +180,8 @@ class QuicStreamFactory::Job {
 
   void OnIOComplete(int rv);
 
+  void CancelWaitForDataReadyCallback();
+
   CompletionCallback callback() {
     return callback_;
   }
@@ -237,7 +237,7 @@ QuicStreamFactory::Job::Job(QuicStreamFactory* factory,
           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,
@@ -311,10 +311,17 @@ void QuicStreamFactory::Job::OnIOComplete(int rv) {
   }
 }
 
+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();
   }
 
@@ -353,6 +360,18 @@ int QuicStreamFactory::Job::DoLoadServerInfo() {
   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()));
@@ -360,7 +379,7 @@ int QuicStreamFactory::Job::DoLoadServerInfo() {
 
 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_);
   }
 
@@ -421,7 +440,7 @@ int QuicStreamFactory::Job::DoConnectComplete(int rv) {
   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;
   }
 
@@ -455,7 +474,7 @@ int QuicStreamRequest::Request(const HostPortPair& host_port_pair,
     net_log_ = net_log;
     callback_ = callback;
   } else {
-    factory_ = NULL;
+    factory_ = nullptr;
   }
   if (rv == OK)
     DCHECK(stream_);
@@ -468,7 +487,7 @@ void QuicStreamRequest::set_stream(scoped_ptr<QuicHttpStream> stream) {
 }
 
 void QuicStreamRequest::OnRequestComplete(int rv) {
-  factory_ = NULL;
+  factory_ = nullptr;
   callback_.Run(rv);
 }
 
@@ -491,32 +510,32 @@ QuicStreamFactory::QuicStreamFactory(
     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");
@@ -570,7 +589,7 @@ int QuicStreamFactory::Create(const HostPortPair& host_port_pair,
     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);
@@ -579,6 +598,11 @@ int QuicStreamFactory::Create(const HostPortPair& host_port_pair,
       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(
@@ -658,7 +682,7 @@ void QuicStreamFactory::OnJobComplete(Job* job, int rv) {
 }
 
 // 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) {
@@ -907,6 +931,7 @@ int QuicStreamFactory::CreateSession(
   config.SetInitialCongestionWindowToSend(
       server_id.is_https() ? kServerSecureInitialCongestionWindow
                            : kServerInecureInitialCongestionWindow);
+  config.set_max_undecryptable_packets(kMaxUndecryptablePackets);
   config.SetInitialFlowControlWindowToSend(kInitialReceiveWindowSize);
   config.SetInitialStreamFlowControlWindowToSend(kInitialReceiveWindowSize);
   config.SetInitialSessionFlowControlWindowToSend(kInitialReceiveWindowSize);
@@ -914,14 +939,22 @@ int QuicStreamFactory::CreateSession(
     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
@@ -934,7 +967,7 @@ int QuicStreamFactory::CreateSession(
                         closed_during_initialize);
   if (closed_during_initialize) {
     DLOG(DFATAL) << "Session closed during initialize";
-    *session = NULL;
+    *session = nullptr;
     return ERR_CONNECTION_CLOSED;
   }
   return OK;
@@ -960,6 +993,8 @@ void QuicStreamFactory::ActivateSession(
 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;
 
@@ -968,6 +1003,27 @@ void QuicStreamFactory::InitializeCachedStateInCryptoConfig(
   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,