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.
4
5#include "net/quic/quic_stream_factory.h"
6
7#include <set>
8
9#include "base/cpu.h"
10#include "base/message_loop/message_loop.h"
11#include "base/message_loop/message_loop_proxy.h"
12#include "base/metrics/histogram.h"
13#include "base/rand_util.h"
14#include "base/stl_util.h"
15#include "base/strings/string_util.h"
16#include "base/values.h"
17#include "net/base/net_errors.h"
18#include "net/cert/cert_verifier.h"
19#include "net/dns/host_resolver.h"
20#include "net/dns/single_request_host_resolver.h"
21#include "net/http/http_server_properties.h"
22#include "net/quic/congestion_control/tcp_receiver.h"
23#include "net/quic/crypto/channel_id_chromium.h"
24#include "net/quic/crypto/proof_verifier_chromium.h"
25#include "net/quic/crypto/quic_random.h"
26#include "net/quic/crypto/quic_server_info.h"
27#include "net/quic/port_suggester.h"
28#include "net/quic/quic_client_session.h"
29#include "net/quic/quic_clock.h"
30#include "net/quic/quic_connection.h"
31#include "net/quic/quic_connection_helper.h"
32#include "net/quic/quic_crypto_client_stream_factory.h"
33#include "net/quic/quic_default_packet_writer.h"
34#include "net/quic/quic_http_stream.h"
35#include "net/quic/quic_protocol.h"
36#include "net/quic/quic_server_id.h"
37#include "net/socket/client_socket_factory.h"
38
39#if defined(OS_WIN)
40#include "base/win/windows_version.h"
41#endif
42
43using std::string;
44using std::vector;
45
46namespace net {
47
48namespace {
49
50enum CreateSessionFailure {
51  CREATION_ERROR_CONNECTING_SOCKET,
52  CREATION_ERROR_SETTING_RECEIVE_BUFFER,
53  CREATION_ERROR_SETTING_SEND_BUFFER,
54  CREATION_ERROR_MAX
55};
56
57// When a connection is idle for 30 seconds it will be closed.
58const int kIdleConnectionTimeoutSeconds = 30;
59
60// The initial receive window size for both streams and sessions.
61const int32 kInitialReceiveWindowSize = 10 * 1024 * 1024;  // 10MB
62
63// The suggested initial congestion windows for a server to use.
64// TODO: This should be tested and optimized, and even better, suggest a window
65// that corresponds to historical bandwidth and min-RTT.
66// Larger initial congestion windows can, if we don't overshoot, reduce latency
67// by avoiding the RTT needed for slow start to double (and re-double) from a
68// default of 10.
69// We match SPDY's use of 32 when secure (since we'd compete with SPDY).
70const int32 kServerSecureInitialCongestionWindow = 32;
71// Be conservative, and just use double a typical TCP  ICWND for HTTP.
72const int32 kServerInecureInitialCongestionWindow = 20;
73
74const char kDummyHostname[] = "quic.global.props";
75const uint16 kDummyPort = 0;
76
77void HistogramCreateSessionFailure(enum CreateSessionFailure error) {
78  UMA_HISTOGRAM_ENUMERATION("Net.QuicSession.CreationError", error,
79                            CREATION_ERROR_MAX);
80}
81
82bool IsEcdsaSupported() {
83#if defined(OS_WIN)
84  if (base::win::GetVersion() < base::win::VERSION_VISTA)
85    return false;
86#endif
87
88  return true;
89}
90
91QuicConfig InitializeQuicConfig(bool enable_time_based_loss_detection,
92                                const QuicTagVector& connection_options) {
93  QuicConfig config;
94  config.SetDefaults();
95  if (enable_time_based_loss_detection)
96    config.SetLossDetectionToSend(kTIME);
97  config.set_idle_connection_state_lifetime(
98      QuicTime::Delta::FromSeconds(kIdleConnectionTimeoutSeconds),
99      QuicTime::Delta::FromSeconds(kIdleConnectionTimeoutSeconds));
100  config.SetConnectionOptionsToSend(connection_options);
101  return config;
102}
103
104class DefaultPacketWriterFactory : public QuicConnection::PacketWriterFactory {
105 public:
106  explicit DefaultPacketWriterFactory(DatagramClientSocket* socket)
107      : socket_(socket) {}
108  virtual ~DefaultPacketWriterFactory() {}
109
110  virtual QuicPacketWriter* Create(QuicConnection* connection) const OVERRIDE;
111
112 private:
113  DatagramClientSocket* socket_;
114};
115
116QuicPacketWriter* DefaultPacketWriterFactory::Create(
117    QuicConnection* connection) const {
118  scoped_ptr<QuicDefaultPacketWriter> writer(
119      new QuicDefaultPacketWriter(socket_));
120  writer->SetConnection(connection);
121  return writer.release();
122}
123
124}  // namespace
125
126QuicStreamFactory::IpAliasKey::IpAliasKey() {}
127
128QuicStreamFactory::IpAliasKey::IpAliasKey(IPEndPoint ip_endpoint,
129                                          bool is_https)
130    : ip_endpoint(ip_endpoint),
131      is_https(is_https) {}
132
133QuicStreamFactory::IpAliasKey::~IpAliasKey() {}
134
135bool QuicStreamFactory::IpAliasKey::operator<(
136    const QuicStreamFactory::IpAliasKey& other) const {
137  if (!(ip_endpoint == other.ip_endpoint)) {
138    return ip_endpoint < other.ip_endpoint;
139  }
140  return is_https < other.is_https;
141}
142
143bool QuicStreamFactory::IpAliasKey::operator==(
144    const QuicStreamFactory::IpAliasKey& other) const {
145  return is_https == other.is_https &&
146      ip_endpoint == other.ip_endpoint;
147};
148
149// Responsible for creating a new QUIC session to the specified server, and
150// for notifying any associated requests when complete.
151class QuicStreamFactory::Job {
152 public:
153  Job(QuicStreamFactory* factory,
154      HostResolver* host_resolver,
155      const HostPortPair& host_port_pair,
156      bool is_https,
157      bool was_alternate_protocol_recently_broken,
158      PrivacyMode privacy_mode,
159      base::StringPiece method,
160      QuicServerInfo* server_info,
161      const BoundNetLog& net_log);
162
163  // Creates a new job to handle the resumption of for connecting an
164  // existing session.
165  Job(QuicStreamFactory* factory,
166      HostResolver* host_resolver,
167      QuicClientSession* session,
168      QuicServerId server_id);
169
170  ~Job();
171
172  int Run(const CompletionCallback& callback);
173
174  int DoLoop(int rv);
175  int DoResolveHost();
176  int DoResolveHostComplete(int rv);
177  int DoLoadServerInfo();
178  int DoLoadServerInfoComplete(int rv);
179  int DoConnect();
180  int DoResumeConnect();
181  int DoConnectComplete(int rv);
182
183  void OnIOComplete(int rv);
184
185  CompletionCallback callback() {
186    return callback_;
187  }
188
189  const QuicServerId server_id() const {
190    return server_id_;
191  }
192
193 private:
194  enum IoState {
195    STATE_NONE,
196    STATE_RESOLVE_HOST,
197    STATE_RESOLVE_HOST_COMPLETE,
198    STATE_LOAD_SERVER_INFO,
199    STATE_LOAD_SERVER_INFO_COMPLETE,
200    STATE_CONNECT,
201    STATE_RESUME_CONNECT,
202    STATE_CONNECT_COMPLETE,
203  };
204  IoState io_state_;
205
206  QuicStreamFactory* factory_;
207  SingleRequestHostResolver host_resolver_;
208  QuicServerId server_id_;
209  bool is_post_;
210  bool was_alternate_protocol_recently_broken_;
211  scoped_ptr<QuicServerInfo> server_info_;
212  const BoundNetLog net_log_;
213  QuicClientSession* session_;
214  CompletionCallback callback_;
215  AddressList address_list_;
216  base::TimeTicks disk_cache_load_start_time_;
217  base::TimeTicks dns_resolution_start_time_;
218  base::WeakPtrFactory<Job> weak_factory_;
219  DISALLOW_COPY_AND_ASSIGN(Job);
220};
221
222QuicStreamFactory::Job::Job(QuicStreamFactory* factory,
223                            HostResolver* host_resolver,
224                            const HostPortPair& host_port_pair,
225                            bool is_https,
226                            bool was_alternate_protocol_recently_broken,
227                            PrivacyMode privacy_mode,
228                            base::StringPiece method,
229                            QuicServerInfo* server_info,
230                            const BoundNetLog& net_log)
231    : io_state_(STATE_RESOLVE_HOST),
232      factory_(factory),
233      host_resolver_(host_resolver),
234      server_id_(host_port_pair, is_https, privacy_mode),
235      is_post_(method == "POST"),
236      was_alternate_protocol_recently_broken_(
237          was_alternate_protocol_recently_broken),
238      server_info_(server_info),
239      net_log_(net_log),
240      session_(NULL),
241      weak_factory_(this) {}
242
243QuicStreamFactory::Job::Job(QuicStreamFactory* factory,
244                            HostResolver* host_resolver,
245                            QuicClientSession* session,
246                            QuicServerId server_id)
247    : io_state_(STATE_RESUME_CONNECT),
248      factory_(factory),
249      host_resolver_(host_resolver),  // unused
250      server_id_(server_id),
251      is_post_(false),  // unused
252      was_alternate_protocol_recently_broken_(false),  // unused
253      net_log_(session->net_log()),  // unused
254      session_(session),
255      weak_factory_(this) {}
256
257QuicStreamFactory::Job::~Job() {
258}
259
260int QuicStreamFactory::Job::Run(const CompletionCallback& callback) {
261  int rv = DoLoop(OK);
262  if (rv == ERR_IO_PENDING)
263    callback_ = callback;
264
265  return rv > 0 ? OK : rv;
266}
267
268int QuicStreamFactory::Job::DoLoop(int rv) {
269  do {
270    IoState state = io_state_;
271    io_state_ = STATE_NONE;
272    switch (state) {
273      case STATE_RESOLVE_HOST:
274        CHECK_EQ(OK, rv);
275        rv = DoResolveHost();
276        break;
277      case STATE_RESOLVE_HOST_COMPLETE:
278        rv = DoResolveHostComplete(rv);
279        break;
280      case STATE_LOAD_SERVER_INFO:
281        CHECK_EQ(OK, rv);
282        rv = DoLoadServerInfo();
283        break;
284      case STATE_LOAD_SERVER_INFO_COMPLETE:
285        rv = DoLoadServerInfoComplete(rv);
286        break;
287      case STATE_CONNECT:
288        CHECK_EQ(OK, rv);
289        rv = DoConnect();
290        break;
291      case STATE_RESUME_CONNECT:
292        CHECK_EQ(OK, rv);
293        rv = DoResumeConnect();
294        break;
295      case STATE_CONNECT_COMPLETE:
296        rv = DoConnectComplete(rv);
297        break;
298      default:
299        NOTREACHED() << "io_state_: " << io_state_;
300        break;
301    }
302  } while (io_state_ != STATE_NONE && rv != ERR_IO_PENDING);
303  return rv;
304}
305
306void QuicStreamFactory::Job::OnIOComplete(int rv) {
307  rv = DoLoop(rv);
308
309  if (rv != ERR_IO_PENDING && !callback_.is_null()) {
310    callback_.Run(rv);
311  }
312}
313
314int QuicStreamFactory::Job::DoResolveHost() {
315  // Start loading the data now, and wait for it after we resolve the host.
316  if (server_info_) {
317    disk_cache_load_start_time_ = base::TimeTicks::Now();
318    server_info_->Start();
319  }
320
321  io_state_ = STATE_RESOLVE_HOST_COMPLETE;
322  dns_resolution_start_time_ = base::TimeTicks::Now();
323  return host_resolver_.Resolve(
324      HostResolver::RequestInfo(server_id_.host_port_pair()),
325      DEFAULT_PRIORITY,
326      &address_list_,
327      base::Bind(&QuicStreamFactory::Job::OnIOComplete,
328                 weak_factory_.GetWeakPtr()),
329      net_log_);
330}
331
332int QuicStreamFactory::Job::DoResolveHostComplete(int rv) {
333  UMA_HISTOGRAM_TIMES("Net.QuicSession.HostResolutionTime",
334                      base::TimeTicks::Now() - dns_resolution_start_time_);
335  if (rv != OK)
336    return rv;
337
338  DCHECK(!factory_->HasActiveSession(server_id_));
339
340  // Inform the factory of this resolution, which will set up
341  // a session alias, if possible.
342  if (factory_->OnResolution(server_id_, address_list_)) {
343    return OK;
344  }
345
346  io_state_ = STATE_LOAD_SERVER_INFO;
347  return OK;
348}
349
350int QuicStreamFactory::Job::DoLoadServerInfo() {
351  io_state_ = STATE_LOAD_SERVER_INFO_COMPLETE;
352
353  if (!server_info_)
354    return OK;
355
356  return server_info_->WaitForDataReady(
357      base::Bind(&QuicStreamFactory::Job::OnIOComplete,
358                 weak_factory_.GetWeakPtr()));
359}
360
361int QuicStreamFactory::Job::DoLoadServerInfoComplete(int rv) {
362  if (server_info_) {
363    UMA_HISTOGRAM_TIMES("Net.QuicServerInfo.DiskCacheReadTime",
364                        base::TimeTicks::Now() - disk_cache_load_start_time_);
365  }
366
367  if (rv != OK) {
368    server_info_.reset();
369  }
370
371  io_state_ = STATE_CONNECT;
372  return OK;
373}
374
375int QuicStreamFactory::Job::DoConnect() {
376  io_state_ = STATE_CONNECT_COMPLETE;
377
378  int rv = factory_->CreateSession(server_id_, server_info_.Pass(),
379                                   address_list_, net_log_, &session_);
380  if (rv != OK) {
381    DCHECK(rv != ERR_IO_PENDING);
382    DCHECK(!session_);
383    return rv;
384  }
385
386  if (!session_->connection()->connected()) {
387    return ERR_CONNECTION_CLOSED;
388  }
389
390  session_->StartReading();
391  if (!session_->connection()->connected()) {
392    return ERR_QUIC_PROTOCOL_ERROR;
393  }
394  bool require_confirmation =
395      factory_->require_confirmation() || is_post_ ||
396      was_alternate_protocol_recently_broken_;
397  rv = session_->CryptoConnect(
398      require_confirmation,
399      base::Bind(&QuicStreamFactory::Job::OnIOComplete,
400                 base::Unretained(this)));
401  return rv;
402}
403
404int QuicStreamFactory::Job::DoResumeConnect() {
405  io_state_ = STATE_CONNECT_COMPLETE;
406
407  int rv = session_->ResumeCryptoConnect(
408      base::Bind(&QuicStreamFactory::Job::OnIOComplete,
409                 base::Unretained(this)));
410
411  return rv;
412}
413
414int QuicStreamFactory::Job::DoConnectComplete(int rv) {
415  if (rv != OK)
416    return rv;
417
418  DCHECK(!factory_->HasActiveSession(server_id_));
419  // There may well now be an active session for this IP.  If so, use the
420  // existing session instead.
421  AddressList address(session_->connection()->peer_address());
422  if (factory_->OnResolution(server_id_, address)) {
423    session_->connection()->SendConnectionClose(QUIC_CONNECTION_IP_POOLED);
424    session_ = NULL;
425    return OK;
426  }
427
428  factory_->ActivateSession(server_id_, session_);
429
430  return OK;
431}
432
433QuicStreamRequest::QuicStreamRequest(QuicStreamFactory* factory)
434    : factory_(factory) {}
435
436QuicStreamRequest::~QuicStreamRequest() {
437  if (factory_ && !callback_.is_null())
438    factory_->CancelRequest(this);
439}
440
441int QuicStreamRequest::Request(const HostPortPair& host_port_pair,
442                               bool is_https,
443                               PrivacyMode privacy_mode,
444                               base::StringPiece method,
445                               const BoundNetLog& net_log,
446                               const CompletionCallback& callback) {
447  DCHECK(!stream_);
448  DCHECK(callback_.is_null());
449  DCHECK(factory_);
450  int rv = factory_->Create(host_port_pair, is_https, privacy_mode, method,
451                            net_log, this);
452  if (rv == ERR_IO_PENDING) {
453    host_port_pair_ = host_port_pair;
454    is_https_ = is_https;
455    net_log_ = net_log;
456    callback_ = callback;
457  } else {
458    factory_ = NULL;
459  }
460  if (rv == OK)
461    DCHECK(stream_);
462  return rv;
463}
464
465void QuicStreamRequest::set_stream(scoped_ptr<QuicHttpStream> stream) {
466  DCHECK(stream);
467  stream_ = stream.Pass();
468}
469
470void QuicStreamRequest::OnRequestComplete(int rv) {
471  factory_ = NULL;
472  callback_.Run(rv);
473}
474
475scoped_ptr<QuicHttpStream> QuicStreamRequest::ReleaseStream() {
476  DCHECK(stream_);
477  return stream_.Pass();
478}
479
480QuicStreamFactory::QuicStreamFactory(
481    HostResolver* host_resolver,
482    ClientSocketFactory* client_socket_factory,
483    base::WeakPtr<HttpServerProperties> http_server_properties,
484    CertVerifier* cert_verifier,
485    ChannelIDService* channel_id_service,
486    TransportSecurityState* transport_security_state,
487    QuicCryptoClientStreamFactory* quic_crypto_client_stream_factory,
488    QuicRandom* random_generator,
489    QuicClock* clock,
490    size_t max_packet_length,
491    const std::string& user_agent_id,
492    const QuicVersionVector& supported_versions,
493    bool enable_port_selection,
494    bool enable_time_based_loss_detection,
495    bool always_require_handshake_confirmation,
496    bool disable_connection_pooling,
497    const QuicTagVector& connection_options)
498    : require_confirmation_(true),
499      host_resolver_(host_resolver),
500      client_socket_factory_(client_socket_factory),
501      http_server_properties_(http_server_properties),
502      transport_security_state_(transport_security_state),
503      quic_server_info_factory_(NULL),
504      quic_crypto_client_stream_factory_(quic_crypto_client_stream_factory),
505      random_generator_(random_generator),
506      clock_(clock),
507      max_packet_length_(max_packet_length),
508      config_(InitializeQuicConfig(enable_time_based_loss_detection,
509                                   connection_options)),
510      supported_versions_(supported_versions),
511      enable_port_selection_(enable_port_selection),
512      always_require_handshake_confirmation_(
513          always_require_handshake_confirmation),
514      disable_connection_pooling_(disable_connection_pooling),
515      port_seed_(random_generator_->RandUint64()),
516      check_persisted_supports_quic_(true),
517      weak_factory_(this) {
518  DCHECK(transport_security_state_);
519  crypto_config_.SetDefaults();
520  crypto_config_.set_user_agent_id(user_agent_id);
521  crypto_config_.AddCanonicalSuffix(".c.youtube.com");
522  crypto_config_.AddCanonicalSuffix(".googlevideo.com");
523  crypto_config_.SetProofVerifier(
524      new ProofVerifierChromium(cert_verifier, transport_security_state));
525  crypto_config_.SetChannelIDSource(
526      new ChannelIDSourceChromium(channel_id_service));
527  base::CPU cpu;
528  if (cpu.has_aesni() && cpu.has_avx())
529    crypto_config_.PreferAesGcm();
530  if (!IsEcdsaSupported())
531    crypto_config_.DisableEcdsa();
532}
533
534QuicStreamFactory::~QuicStreamFactory() {
535  CloseAllSessions(ERR_ABORTED);
536  while (!all_sessions_.empty()) {
537    delete all_sessions_.begin()->first;
538    all_sessions_.erase(all_sessions_.begin());
539  }
540  STLDeleteValues(&active_jobs_);
541}
542
543void QuicStreamFactory::set_require_confirmation(bool require_confirmation) {
544  require_confirmation_ = require_confirmation;
545  if (http_server_properties_ && (!(local_address_ == IPEndPoint()))) {
546    // TODO(rtenneti): Delete host_port_pair and persist data in globals.
547    HostPortPair host_port_pair(kDummyHostname, kDummyPort);
548    http_server_properties_->SetSupportsQuic(
549        host_port_pair, !require_confirmation,
550        local_address_.ToStringWithoutPort());
551  }
552}
553
554int QuicStreamFactory::Create(const HostPortPair& host_port_pair,
555                              bool is_https,
556                              PrivacyMode privacy_mode,
557                              base::StringPiece method,
558                              const BoundNetLog& net_log,
559                              QuicStreamRequest* request) {
560  QuicServerId server_id(host_port_pair, is_https, privacy_mode);
561  if (HasActiveSession(server_id)) {
562    request->set_stream(CreateIfSessionExists(server_id, net_log));
563    return OK;
564  }
565
566  if (HasActiveJob(server_id)) {
567    Job* job = active_jobs_[server_id];
568    active_requests_[request] = job;
569    job_requests_map_[job].insert(request);
570    return ERR_IO_PENDING;
571  }
572
573  QuicServerInfo* quic_server_info = NULL;
574  if (quic_server_info_factory_) {
575    QuicCryptoClientConfig::CachedState* cached =
576        crypto_config_.LookupOrCreate(server_id);
577    DCHECK(cached);
578    if (cached->IsEmpty()) {
579      quic_server_info = quic_server_info_factory_->GetForServer(server_id);
580    }
581  }
582  bool was_alternate_protocol_recently_broken =
583      http_server_properties_ &&
584      http_server_properties_->WasAlternateProtocolRecentlyBroken(
585          server_id.host_port_pair());
586  scoped_ptr<Job> job(new Job(this, host_resolver_, host_port_pair, is_https,
587                              was_alternate_protocol_recently_broken,
588                              privacy_mode, method, quic_server_info, net_log));
589  int rv = job->Run(base::Bind(&QuicStreamFactory::OnJobComplete,
590                               base::Unretained(this), job.get()));
591
592  if (rv == ERR_IO_PENDING) {
593    active_requests_[request] = job.get();
594    job_requests_map_[job.get()].insert(request);
595    active_jobs_[server_id] = job.release();
596  }
597  if (rv == OK) {
598    DCHECK(HasActiveSession(server_id));
599    request->set_stream(CreateIfSessionExists(server_id, net_log));
600  }
601  return rv;
602}
603
604bool QuicStreamFactory::OnResolution(
605    const QuicServerId& server_id,
606    const AddressList& address_list) {
607  DCHECK(!HasActiveSession(server_id));
608  if (disable_connection_pooling_) {
609    return false;
610  }
611  for (size_t i = 0; i < address_list.size(); ++i) {
612    const IPEndPoint& address = address_list[i];
613    const IpAliasKey ip_alias_key(address, server_id.is_https());
614    if (!ContainsKey(ip_aliases_, ip_alias_key))
615      continue;
616
617    const SessionSet& sessions = ip_aliases_[ip_alias_key];
618    for (SessionSet::const_iterator i = sessions.begin();
619         i != sessions.end(); ++i) {
620      QuicClientSession* session = *i;
621      if (!session->CanPool(server_id.host()))
622        continue;
623      active_sessions_[server_id] = session;
624      session_aliases_[session].insert(server_id);
625      return true;
626    }
627  }
628  return false;
629}
630
631void QuicStreamFactory::OnJobComplete(Job* job, int rv) {
632  if (rv == OK) {
633    if (!always_require_handshake_confirmation_)
634      set_require_confirmation(false);
635
636    // Create all the streams, but do not notify them yet.
637    for (RequestSet::iterator it = job_requests_map_[job].begin();
638         it != job_requests_map_[job].end() ; ++it) {
639      DCHECK(HasActiveSession(job->server_id()));
640      (*it)->set_stream(CreateIfSessionExists(job->server_id(),
641                                              (*it)->net_log()));
642    }
643  }
644  while (!job_requests_map_[job].empty()) {
645    RequestSet::iterator it = job_requests_map_[job].begin();
646    QuicStreamRequest* request = *it;
647    job_requests_map_[job].erase(it);
648    active_requests_.erase(request);
649    // Even though we're invoking callbacks here, we don't need to worry
650    // about |this| being deleted, because the factory is owned by the
651    // profile which can not be deleted via callbacks.
652    request->OnRequestComplete(rv);
653  }
654  active_jobs_.erase(job->server_id());
655  job_requests_map_.erase(job);
656  delete job;
657  return;
658}
659
660// Returns a newly created QuicHttpStream owned by the caller, if a
661// matching session already exists.  Returns NULL otherwise.
662scoped_ptr<QuicHttpStream> QuicStreamFactory::CreateIfSessionExists(
663    const QuicServerId& server_id,
664    const BoundNetLog& net_log) {
665  if (!HasActiveSession(server_id)) {
666    DVLOG(1) << "No active session";
667    return scoped_ptr<QuicHttpStream>();
668  }
669
670  QuicClientSession* session = active_sessions_[server_id];
671  DCHECK(session);
672  return scoped_ptr<QuicHttpStream>(
673      new QuicHttpStream(session->GetWeakPtr()));
674}
675
676void QuicStreamFactory::OnIdleSession(QuicClientSession* session) {
677}
678
679void QuicStreamFactory::OnSessionGoingAway(QuicClientSession* session) {
680  const AliasSet& aliases = session_aliases_[session];
681  for (AliasSet::const_iterator it = aliases.begin(); it != aliases.end();
682       ++it) {
683    DCHECK(active_sessions_.count(*it));
684    DCHECK_EQ(session, active_sessions_[*it]);
685    // Track sessions which have recently gone away so that we can disable
686    // port suggestions.
687    if (session->goaway_received()) {
688      gone_away_aliases_.insert(*it);
689    }
690
691    active_sessions_.erase(*it);
692    ProcessGoingAwaySession(session, *it, true);
693  }
694  ProcessGoingAwaySession(session, all_sessions_[session], false);
695  if (!aliases.empty()) {
696    const IpAliasKey ip_alias_key(session->connection()->peer_address(),
697                                  aliases.begin()->is_https());
698    ip_aliases_[ip_alias_key].erase(session);
699    if (ip_aliases_[ip_alias_key].empty()) {
700      ip_aliases_.erase(ip_alias_key);
701    }
702  }
703  session_aliases_.erase(session);
704}
705
706void QuicStreamFactory::OnSessionClosed(QuicClientSession* session) {
707  DCHECK_EQ(0u, session->GetNumOpenStreams());
708  OnSessionGoingAway(session);
709  delete session;
710  all_sessions_.erase(session);
711}
712
713void QuicStreamFactory::OnSessionConnectTimeout(
714    QuicClientSession* session) {
715  const AliasSet& aliases = session_aliases_[session];
716  for (AliasSet::const_iterator it = aliases.begin(); it != aliases.end();
717       ++it) {
718    DCHECK(active_sessions_.count(*it));
719    DCHECK_EQ(session, active_sessions_[*it]);
720    active_sessions_.erase(*it);
721  }
722
723  if (aliases.empty()) {
724    return;
725  }
726
727  const IpAliasKey ip_alias_key(session->connection()->peer_address(),
728                                aliases.begin()->is_https());
729  ip_aliases_[ip_alias_key].erase(session);
730  if (ip_aliases_[ip_alias_key].empty()) {
731    ip_aliases_.erase(ip_alias_key);
732  }
733  QuicServerId server_id = *aliases.begin();
734  session_aliases_.erase(session);
735  Job* job = new Job(this, host_resolver_, session, server_id);
736  active_jobs_[server_id] = job;
737  int rv = job->Run(base::Bind(&QuicStreamFactory::OnJobComplete,
738                               base::Unretained(this), job));
739  DCHECK_EQ(ERR_IO_PENDING, rv);
740}
741
742void QuicStreamFactory::CancelRequest(QuicStreamRequest* request) {
743  DCHECK(ContainsKey(active_requests_, request));
744  Job* job = active_requests_[request];
745  job_requests_map_[job].erase(request);
746  active_requests_.erase(request);
747}
748
749void QuicStreamFactory::CloseAllSessions(int error) {
750  while (!active_sessions_.empty()) {
751    size_t initial_size = active_sessions_.size();
752    active_sessions_.begin()->second->CloseSessionOnError(error);
753    DCHECK_NE(initial_size, active_sessions_.size());
754  }
755  while (!all_sessions_.empty()) {
756    size_t initial_size = all_sessions_.size();
757    all_sessions_.begin()->first->CloseSessionOnError(error);
758    DCHECK_NE(initial_size, all_sessions_.size());
759  }
760  DCHECK(all_sessions_.empty());
761}
762
763base::Value* QuicStreamFactory::QuicStreamFactoryInfoToValue() const {
764  base::ListValue* list = new base::ListValue();
765
766  for (SessionMap::const_iterator it = active_sessions_.begin();
767       it != active_sessions_.end(); ++it) {
768    const QuicServerId& server_id = it->first;
769    QuicClientSession* session = it->second;
770    const AliasSet& aliases = session_aliases_.find(session)->second;
771    // Only add a session to the list once.
772    if (server_id == *aliases.begin()) {
773      std::set<HostPortPair> hosts;
774      for (AliasSet::const_iterator alias_it = aliases.begin();
775           alias_it != aliases.end(); ++alias_it) {
776        hosts.insert(alias_it->host_port_pair());
777      }
778      list->Append(session->GetInfoAsValue(hosts));
779    }
780  }
781  return list;
782}
783
784void QuicStreamFactory::ClearCachedStatesInCryptoConfig() {
785  crypto_config_.ClearCachedStates();
786}
787
788void QuicStreamFactory::OnIPAddressChanged() {
789  CloseAllSessions(ERR_NETWORK_CHANGED);
790  set_require_confirmation(true);
791}
792
793void QuicStreamFactory::OnCertAdded(const X509Certificate* cert) {
794  CloseAllSessions(ERR_CERT_DATABASE_CHANGED);
795}
796
797void QuicStreamFactory::OnCACertChanged(const X509Certificate* cert) {
798  // We should flush the sessions if we removed trust from a
799  // cert, because a previously trusted server may have become
800  // untrusted.
801  //
802  // We should not flush the sessions if we added trust to a cert.
803  //
804  // Since the OnCACertChanged method doesn't tell us what
805  // kind of change it is, we have to flush the socket
806  // pools to be safe.
807  CloseAllSessions(ERR_CERT_DATABASE_CHANGED);
808}
809
810bool QuicStreamFactory::HasActiveSession(
811    const QuicServerId& server_id) const {
812  return ContainsKey(active_sessions_, server_id);
813}
814
815int QuicStreamFactory::CreateSession(
816    const QuicServerId& server_id,
817    scoped_ptr<QuicServerInfo> server_info,
818    const AddressList& address_list,
819    const BoundNetLog& net_log,
820    QuicClientSession** session) {
821  bool enable_port_selection = enable_port_selection_;
822  if (enable_port_selection &&
823      ContainsKey(gone_away_aliases_, server_id)) {
824    // Disable port selection when the server is going away.
825    // There is no point in trying to return to the same server, if
826    // that server is no longer handling requests.
827    enable_port_selection = false;
828    gone_away_aliases_.erase(server_id);
829  }
830
831  QuicConnectionId connection_id = random_generator_->RandUint64();
832  IPEndPoint addr = *address_list.begin();
833  scoped_refptr<PortSuggester> port_suggester =
834      new PortSuggester(server_id.host_port_pair(), port_seed_);
835  DatagramSocket::BindType bind_type = enable_port_selection ?
836      DatagramSocket::RANDOM_BIND :  // Use our callback.
837      DatagramSocket::DEFAULT_BIND;  // Use OS to randomize.
838  scoped_ptr<DatagramClientSocket> socket(
839      client_socket_factory_->CreateDatagramClientSocket(
840          bind_type,
841          base::Bind(&PortSuggester::SuggestPort, port_suggester),
842          net_log.net_log(), net_log.source()));
843  int rv = socket->Connect(addr);
844  if (rv != OK) {
845    HistogramCreateSessionFailure(CREATION_ERROR_CONNECTING_SOCKET);
846    return rv;
847  }
848  UMA_HISTOGRAM_COUNTS("Net.QuicEphemeralPortsSuggested",
849                       port_suggester->call_count());
850  if (enable_port_selection) {
851    DCHECK_LE(1u, port_suggester->call_count());
852  } else {
853    DCHECK_EQ(0u, port_suggester->call_count());
854  }
855
856  // We should adaptively set this buffer size, but for now, we'll use a size
857  // that is more than large enough for a full receive window, and yet
858  // does not consume "too much" memory.  If we see bursty packet loss, we may
859  // revisit this setting and test for its impact.
860  const int32 kSocketBufferSize(TcpReceiver::kReceiveWindowTCP);
861  rv = socket->SetReceiveBufferSize(kSocketBufferSize);
862  if (rv != OK) {
863    HistogramCreateSessionFailure(CREATION_ERROR_SETTING_RECEIVE_BUFFER);
864    return rv;
865  }
866  // Set a buffer large enough to contain the initial CWND's worth of packet
867  // to work around the problem with CHLO packets being sent out with the
868  // wrong encryption level, when the send buffer is full.
869  rv = socket->SetSendBufferSize(kMaxPacketSize * 20);
870  if (rv != OK) {
871    HistogramCreateSessionFailure(CREATION_ERROR_SETTING_SEND_BUFFER);
872    return rv;
873  }
874
875  socket->GetLocalAddress(&local_address_);
876  if (check_persisted_supports_quic_ && http_server_properties_) {
877    check_persisted_supports_quic_ = false;
878    // TODO(rtenneti): Delete host_port_pair and persist data in globals.
879    HostPortPair host_port_pair(kDummyHostname, kDummyPort);
880    SupportsQuic supports_quic(true, local_address_.ToStringWithoutPort());
881    if (http_server_properties_->GetSupportsQuic(
882            host_port_pair).Equals(supports_quic)) {
883      require_confirmation_ = false;
884    }
885  }
886
887  DefaultPacketWriterFactory packet_writer_factory(socket.get());
888
889  if (!helper_.get()) {
890    helper_.reset(new QuicConnectionHelper(
891        base::MessageLoop::current()->message_loop_proxy().get(),
892        clock_.get(), random_generator_));
893  }
894
895  QuicConnection* connection = new QuicConnection(connection_id,
896                                                  addr,
897                                                  helper_.get(),
898                                                  packet_writer_factory,
899                                                  true  /* owns_writer */,
900                                                  false  /* is_server */,
901                                                  supported_versions_);
902  connection->set_max_packet_length(max_packet_length_);
903
904  InitializeCachedStateInCryptoConfig(server_id, server_info);
905
906  QuicConfig config = config_;
907  config.SetInitialCongestionWindowToSend(
908      server_id.is_https() ? kServerSecureInitialCongestionWindow
909                           : kServerInecureInitialCongestionWindow);
910  config.SetInitialFlowControlWindowToSend(kInitialReceiveWindowSize);
911  config.SetInitialStreamFlowControlWindowToSend(kInitialReceiveWindowSize);
912  config.SetInitialSessionFlowControlWindowToSend(kInitialReceiveWindowSize);
913  if (http_server_properties_) {
914    const HttpServerProperties::NetworkStats* stats =
915        http_server_properties_->GetServerNetworkStats(
916            server_id.host_port_pair());
917    if (stats != NULL) {
918      config.SetInitialRoundTripTimeUsToSend(stats->srtt.InMicroseconds());
919    }
920  }
921
922  *session = new QuicClientSession(
923      connection, socket.Pass(), this, transport_security_state_,
924      server_info.Pass(), config,
925      base::MessageLoop::current()->message_loop_proxy().get(),
926      net_log.net_log());
927  all_sessions_[*session] = server_id;  // owning pointer
928  (*session)->InitializeSession(server_id,  &crypto_config_,
929                                quic_crypto_client_stream_factory_);
930  bool closed_during_initialize =
931      !ContainsKey(all_sessions_, *session) ||
932      !(*session)->connection()->connected();
933  UMA_HISTOGRAM_BOOLEAN("Net.QuicSession.ClosedDuringInitializeSession",
934                        closed_during_initialize);
935  if (closed_during_initialize) {
936    DLOG(DFATAL) << "Session closed during initialize";
937    *session = NULL;
938    return ERR_CONNECTION_CLOSED;
939  }
940  return OK;
941}
942
943bool QuicStreamFactory::HasActiveJob(const QuicServerId& key) const {
944  return ContainsKey(active_jobs_, key);
945}
946
947void QuicStreamFactory::ActivateSession(
948    const QuicServerId& server_id,
949    QuicClientSession* session) {
950  DCHECK(!HasActiveSession(server_id));
951  UMA_HISTOGRAM_COUNTS("Net.QuicActiveSessions", active_sessions_.size());
952  active_sessions_[server_id] = session;
953  session_aliases_[session].insert(server_id);
954  const IpAliasKey ip_alias_key(session->connection()->peer_address(),
955                                server_id.is_https());
956  DCHECK(!ContainsKey(ip_aliases_[ip_alias_key], session));
957  ip_aliases_[ip_alias_key].insert(session);
958}
959
960void QuicStreamFactory::InitializeCachedStateInCryptoConfig(
961    const QuicServerId& server_id,
962    const scoped_ptr<QuicServerInfo>& server_info) {
963  if (!server_info)
964    return;
965
966  QuicCryptoClientConfig::CachedState* cached =
967      crypto_config_.LookupOrCreate(server_id);
968  if (!cached->IsEmpty())
969    return;
970
971  if (!cached->Initialize(server_info->state().server_config,
972                          server_info->state().source_address_token,
973                          server_info->state().certs,
974                          server_info->state().server_config_sig,
975                          clock_->WallNow()))
976    return;
977
978  if (!server_id.is_https()) {
979    // Don't check the certificates for insecure QUIC.
980    cached->SetProofValid();
981  }
982}
983
984void QuicStreamFactory::ProcessGoingAwaySession(
985    QuicClientSession* session,
986    const QuicServerId& server_id,
987    bool session_was_active) {
988  if (!http_server_properties_)
989    return;
990
991  const QuicConnectionStats& stats = session->connection()->GetStats();
992  if (session->IsCryptoHandshakeConfirmed()) {
993    HttpServerProperties::NetworkStats network_stats;
994    network_stats.srtt = base::TimeDelta::FromMicroseconds(stats.srtt_us);
995    network_stats.bandwidth_estimate = stats.estimated_bandwidth;
996    http_server_properties_->SetServerNetworkStats(server_id.host_port_pair(),
997                                                   network_stats);
998    return;
999  }
1000
1001  UMA_HISTOGRAM_COUNTS("Net.QuicHandshakeNotConfirmedNumPacketsReceived",
1002                       stats.packets_received);
1003
1004  if (!session_was_active)
1005    return;
1006
1007  const HostPortPair& server = server_id.host_port_pair();
1008  // Don't try to change the alternate-protocol state, if the
1009  // alternate-protocol state is unknown.
1010  if (!http_server_properties_->HasAlternateProtocol(server))
1011    return;
1012
1013  // TODO(rch):  In the special case where the session has received no
1014  // packets from the peer, we should consider blacklisting this
1015  // differently so that we still race TCP but we don't consider the
1016  // session connected until the handshake has been confirmed.
1017  HistogramBrokenAlternateProtocolLocation(
1018      BROKEN_ALTERNATE_PROTOCOL_LOCATION_QUIC_STREAM_FACTORY);
1019  AlternateProtocolInfo alternate =
1020      http_server_properties_->GetAlternateProtocol(server);
1021  DCHECK_EQ(QUIC, alternate.protocol);
1022
1023  // Since the session was active, there's no longer an
1024  // HttpStreamFactoryImpl::Job running which can mark it broken, unless the
1025  // TCP job also fails. So to avoid not using QUIC when we otherwise could,
1026  // we mark it as broken, and then immediately re-enable it. This leaves
1027  // QUIC as "recently broken" which means that 0-RTT will be disabled but
1028  // we'll still race.
1029  http_server_properties_->SetBrokenAlternateProtocol(server);
1030  http_server_properties_->ClearAlternateProtocol(server);
1031  http_server_properties_->SetAlternateProtocol(
1032      server, alternate.port, alternate.protocol, 1);
1033  DCHECK_EQ(QUIC,
1034            http_server_properties_->GetAlternateProtocol(server).protocol);
1035  DCHECK(http_server_properties_->WasAlternateProtocolRecentlyBroken(
1036      server));
1037}
1038
1039}  // namespace net
1040