| 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 <set> | 7 #include <set> |
| 8 | 8 |
| 9 #include "base/message_loop/message_loop.h" | 9 #include "base/message_loop/message_loop.h" |
| 10 #include "base/message_loop/message_loop_proxy.h" | 10 #include "base/message_loop/message_loop_proxy.h" |
| (...skipping 53 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 64 // Responsible for creating a new QUIC session to the specified server, and | 64 // Responsible for creating a new QUIC session to the specified server, and |
| 65 // for notifying any associated requests when complete. | 65 // for notifying any associated requests when complete. |
| 66 class QuicStreamFactory::Job { | 66 class QuicStreamFactory::Job { |
| 67 public: | 67 public: |
| 68 Job(QuicStreamFactory* factory, | 68 Job(QuicStreamFactory* factory, |
| 69 HostResolver* host_resolver, | 69 HostResolver* host_resolver, |
| 70 const HostPortPair& host_port_pair, | 70 const HostPortPair& host_port_pair, |
| 71 bool is_https, | 71 bool is_https, |
| 72 base::StringPiece method, | 72 base::StringPiece method, |
| 73 CertVerifier* cert_verifier, | 73 CertVerifier* cert_verifier, |
| 74 QuicServerInfo* server_info, |
| 74 const BoundNetLog& net_log); | 75 const BoundNetLog& net_log); |
| 75 | 76 |
| 76 ~Job(); | 77 ~Job(); |
| 77 | 78 |
| 78 int Run(const CompletionCallback& callback); | 79 int Run(const CompletionCallback& callback); |
| 79 | 80 |
| 80 int DoLoop(int rv); | 81 int DoLoop(int rv); |
| 82 int DoLoadServerInfo(); |
| 83 int DoLoadServerInfoComplete(int rv); |
| 81 int DoResolveHost(); | 84 int DoResolveHost(); |
| 82 int DoResolveHostComplete(int rv); | 85 int DoResolveHostComplete(int rv); |
| 83 int DoConnect(); | 86 int DoConnect(); |
| 84 int DoConnectComplete(int rv); | 87 int DoConnectComplete(int rv); |
| 85 | 88 |
| 86 void OnIOComplete(int rv); | 89 void OnIOComplete(int rv); |
| 87 | 90 |
| 88 CompletionCallback callback() { | 91 CompletionCallback callback() { |
| 89 return callback_; | 92 return callback_; |
| 90 } | 93 } |
| 91 | 94 |
| 92 const QuicSessionKey session_key() const { | 95 const QuicSessionKey session_key() const { |
| 93 return session_key_; | 96 return session_key_; |
| 94 } | 97 } |
| 95 | 98 |
| 96 private: | 99 private: |
| 97 enum IoState { | 100 enum IoState { |
| 98 STATE_NONE, | 101 STATE_NONE, |
| 102 STATE_LOAD_SERVER_INFO, |
| 103 STATE_LOAD_SERVER_INFO_COMPLETE, |
| 99 STATE_RESOLVE_HOST, | 104 STATE_RESOLVE_HOST, |
| 100 STATE_RESOLVE_HOST_COMPLETE, | 105 STATE_RESOLVE_HOST_COMPLETE, |
| 101 STATE_CONNECT, | 106 STATE_CONNECT, |
| 102 STATE_CONNECT_COMPLETE, | 107 STATE_CONNECT_COMPLETE, |
| 103 }; | 108 }; |
| 104 IoState io_state_; | 109 IoState io_state_; |
| 105 | 110 |
| 106 QuicStreamFactory* factory_; | 111 QuicStreamFactory* factory_; |
| 107 SingleRequestHostResolver host_resolver_; | 112 SingleRequestHostResolver host_resolver_; |
| 108 bool is_https_; | 113 bool is_https_; |
| 109 QuicSessionKey session_key_; | 114 QuicSessionKey session_key_; |
| 110 bool is_post_; | 115 bool is_post_; |
| 111 CertVerifier* cert_verifier_; | 116 CertVerifier* cert_verifier_; |
| 117 scoped_ptr<QuicServerInfo> server_info_; |
| 112 const BoundNetLog net_log_; | 118 const BoundNetLog net_log_; |
| 113 QuicClientSession* session_; | 119 QuicClientSession* session_; |
| 114 CompletionCallback callback_; | 120 CompletionCallback callback_; |
| 115 AddressList address_list_; | 121 AddressList address_list_; |
| 116 DISALLOW_COPY_AND_ASSIGN(Job); | 122 DISALLOW_COPY_AND_ASSIGN(Job); |
| 117 }; | 123 }; |
| 118 | 124 |
| 119 QuicStreamFactory::Job::Job(QuicStreamFactory* factory, | 125 QuicStreamFactory::Job::Job(QuicStreamFactory* factory, |
| 120 HostResolver* host_resolver, | 126 HostResolver* host_resolver, |
| 121 const HostPortPair& host_port_pair, | 127 const HostPortPair& host_port_pair, |
| 122 bool is_https, | 128 bool is_https, |
| 123 base::StringPiece method, | 129 base::StringPiece method, |
| 124 CertVerifier* cert_verifier, | 130 CertVerifier* cert_verifier, |
| 131 QuicServerInfo* server_info, |
| 125 const BoundNetLog& net_log) | 132 const BoundNetLog& net_log) |
| 126 : factory_(factory), | 133 : factory_(factory), |
| 127 host_resolver_(host_resolver), | 134 host_resolver_(host_resolver), |
| 128 is_https_(is_https), | 135 is_https_(is_https), |
| 129 session_key_(host_port_pair, is_https), | 136 session_key_(host_port_pair, is_https), |
| 130 is_post_(method == "POST"), | 137 is_post_(method == "POST"), |
| 131 cert_verifier_(cert_verifier), | 138 cert_verifier_(cert_verifier), |
| 139 server_info_(server_info), |
| 132 net_log_(net_log), | 140 net_log_(net_log), |
| 133 session_(NULL) {} | 141 session_(NULL) {} |
| 134 | 142 |
| 135 QuicStreamFactory::Job::~Job() { | 143 QuicStreamFactory::Job::~Job() { |
| 136 } | 144 } |
| 137 | 145 |
| 138 int QuicStreamFactory::Job::Run(const CompletionCallback& callback) { | 146 int QuicStreamFactory::Job::Run(const CompletionCallback& callback) { |
| 139 io_state_ = STATE_RESOLVE_HOST; | 147 io_state_ = STATE_LOAD_SERVER_INFO; |
| 140 int rv = DoLoop(OK); | 148 int rv = DoLoop(OK); |
| 141 if (rv == ERR_IO_PENDING) | 149 if (rv == ERR_IO_PENDING) |
| 142 callback_ = callback; | 150 callback_ = callback; |
| 143 | 151 |
| 144 return rv > 0 ? OK : rv; | 152 return rv > 0 ? OK : rv; |
| 145 } | 153 } |
| 146 | 154 |
| 147 int QuicStreamFactory::Job::DoLoop(int rv) { | 155 int QuicStreamFactory::Job::DoLoop(int rv) { |
| 148 do { | 156 do { |
| 149 IoState state = io_state_; | 157 IoState state = io_state_; |
| 150 io_state_ = STATE_NONE; | 158 io_state_ = STATE_NONE; |
| 151 switch (state) { | 159 switch (state) { |
| 160 case STATE_LOAD_SERVER_INFO: |
| 161 CHECK_EQ(OK, rv); |
| 162 rv = DoLoadServerInfo(); |
| 163 break; |
| 164 case STATE_LOAD_SERVER_INFO_COMPLETE: |
| 165 rv = DoLoadServerInfoComplete(rv); |
| 166 break; |
| 152 case STATE_RESOLVE_HOST: | 167 case STATE_RESOLVE_HOST: |
| 153 CHECK_EQ(OK, rv); | 168 CHECK_EQ(OK, rv); |
| 154 rv = DoResolveHost(); | 169 rv = DoResolveHost(); |
| 155 break; | 170 break; |
| 156 case STATE_RESOLVE_HOST_COMPLETE: | 171 case STATE_RESOLVE_HOST_COMPLETE: |
| 157 rv = DoResolveHostComplete(rv); | 172 rv = DoResolveHostComplete(rv); |
| 158 break; | 173 break; |
| 159 case STATE_CONNECT: | 174 case STATE_CONNECT: |
| 160 CHECK_EQ(OK, rv); | 175 CHECK_EQ(OK, rv); |
| 161 rv = DoConnect(); | 176 rv = DoConnect(); |
| (...skipping 10 matching lines...) Expand all Loading... |
| 172 } | 187 } |
| 173 | 188 |
| 174 void QuicStreamFactory::Job::OnIOComplete(int rv) { | 189 void QuicStreamFactory::Job::OnIOComplete(int rv) { |
| 175 rv = DoLoop(rv); | 190 rv = DoLoop(rv); |
| 176 | 191 |
| 177 if (rv != ERR_IO_PENDING && !callback_.is_null()) { | 192 if (rv != ERR_IO_PENDING && !callback_.is_null()) { |
| 178 callback_.Run(rv); | 193 callback_.Run(rv); |
| 179 } | 194 } |
| 180 } | 195 } |
| 181 | 196 |
| 197 int QuicStreamFactory::Job::DoLoadServerInfo() { |
| 198 io_state_ = STATE_LOAD_SERVER_INFO_COMPLETE; |
| 199 |
| 200 if (server_info_) |
| 201 server_info_->Start(); |
| 202 |
| 203 return OK; |
| 204 } |
| 205 |
| 206 int QuicStreamFactory::Job::DoLoadServerInfoComplete(int rv) { |
| 207 if (rv != OK) |
| 208 return rv; |
| 209 |
| 210 io_state_ = STATE_RESOLVE_HOST; |
| 211 return OK; |
| 212 } |
| 213 |
| 182 int QuicStreamFactory::Job::DoResolveHost() { | 214 int QuicStreamFactory::Job::DoResolveHost() { |
| 183 io_state_ = STATE_RESOLVE_HOST_COMPLETE; | 215 io_state_ = STATE_RESOLVE_HOST_COMPLETE; |
| 184 return host_resolver_.Resolve( | 216 return host_resolver_.Resolve( |
| 185 HostResolver::RequestInfo(session_key_.host_port_pair()), | 217 HostResolver::RequestInfo(session_key_.host_port_pair()), |
| 186 DEFAULT_PRIORITY, | 218 DEFAULT_PRIORITY, |
| 187 &address_list_, | 219 &address_list_, |
| 188 base::Bind(&QuicStreamFactory::Job::OnIOComplete, base::Unretained(this)), | 220 base::Bind(&QuicStreamFactory::Job::OnIOComplete, base::Unretained(this)), |
| 189 net_log_); | 221 net_log_); |
| 190 } | 222 } |
| 191 | 223 |
| (...skipping 58 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 250 | 282 |
| 251 scoped_ptr<QuicHttpStream> QuicStreamRequest::ReleaseStream() { | 283 scoped_ptr<QuicHttpStream> QuicStreamRequest::ReleaseStream() { |
| 252 DCHECK(stream_); | 284 DCHECK(stream_); |
| 253 return stream_.Pass(); | 285 return stream_.Pass(); |
| 254 } | 286 } |
| 255 | 287 |
| 256 int QuicStreamFactory::Job::DoConnect() { | 288 int QuicStreamFactory::Job::DoConnect() { |
| 257 io_state_ = STATE_CONNECT_COMPLETE; | 289 io_state_ = STATE_CONNECT_COMPLETE; |
| 258 | 290 |
| 259 int rv = factory_->CreateSession(session_key_.host_port_pair(), is_https_, | 291 int rv = factory_->CreateSession(session_key_.host_port_pair(), is_https_, |
| 260 cert_verifier_, address_list_, net_log_, &session_); | 292 cert_verifier_, server_info_.Pass(), |
| 293 address_list_, net_log_, &session_); |
| 261 if (rv != OK) { | 294 if (rv != OK) { |
| 262 DCHECK(rv != ERR_IO_PENDING); | 295 DCHECK(rv != ERR_IO_PENDING); |
| 263 DCHECK(!session_); | 296 DCHECK(!session_); |
| 264 return rv; | 297 return rv; |
| 265 } | 298 } |
| 266 | 299 |
| 267 session_->StartReading(); | 300 session_->StartReading(); |
| 268 if (!session_->connection()->connected()) { | 301 if (!session_->connection()->connected()) { |
| 269 return ERR_QUIC_PROTOCOL_ERROR; | 302 return ERR_QUIC_PROTOCOL_ERROR; |
| 270 } | 303 } |
| (...skipping 77 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 348 return OK; | 381 return OK; |
| 349 } | 382 } |
| 350 | 383 |
| 351 if (HasActiveJob(session_key)) { | 384 if (HasActiveJob(session_key)) { |
| 352 Job* job = active_jobs_[session_key]; | 385 Job* job = active_jobs_[session_key]; |
| 353 active_requests_[request] = job; | 386 active_requests_[request] = job; |
| 354 job_requests_map_[job].insert(request); | 387 job_requests_map_[job].insert(request); |
| 355 return ERR_IO_PENDING; | 388 return ERR_IO_PENDING; |
| 356 } | 389 } |
| 357 | 390 |
| 358 // Create crypto config and start the process of loading QUIC server | 391 QuicServerInfo* quic_server_info = NULL; |
| 359 // information from disk cache. | 392 if (quic_server_info_factory_) { |
| 360 QuicCryptoClientConfig* crypto_config = GetOrCreateCryptoConfig(session_key); | 393 QuicCryptoClientConfig* crypto_config = |
| 361 DCHECK(crypto_config); | 394 GetOrCreateCryptoConfig(session_key); |
| 362 | 395 QuicCryptoClientConfig::CachedState* cached = |
| 396 crypto_config->LookupOrCreate(session_key.host_port_pair().host()); |
| 397 DCHECK(cached); |
| 398 if (cached->IsEmpty()) { |
| 399 quic_server_info = |
| 400 quic_server_info_factory_->GetForHost(host_port_pair.host()); |
| 401 } |
| 402 } |
| 363 scoped_ptr<Job> job(new Job(this, host_resolver_, host_port_pair, | 403 scoped_ptr<Job> job(new Job(this, host_resolver_, host_port_pair, |
| 364 is_https, method, cert_verifier, net_log)); | 404 is_https, method, cert_verifier, |
| 405 quic_server_info, net_log)); |
| 365 int rv = job->Run(base::Bind(&QuicStreamFactory::OnJobComplete, | 406 int rv = job->Run(base::Bind(&QuicStreamFactory::OnJobComplete, |
| 366 base::Unretained(this), job.get())); | 407 base::Unretained(this), job.get())); |
| 367 | 408 |
| 368 if (rv == ERR_IO_PENDING) { | 409 if (rv == ERR_IO_PENDING) { |
| 369 active_requests_[request] = job.get(); | 410 active_requests_[request] = job.get(); |
| 370 job_requests_map_[job.get()].insert(request); | 411 job_requests_map_[job.get()].insert(request); |
| 371 active_jobs_[session_key] = job.release(); | 412 active_jobs_[session_key] = job.release(); |
| 372 } | 413 } |
| 373 if (rv == OK) { | 414 if (rv == OK) { |
| 374 DCHECK(HasActiveSession(session_key)); | 415 DCHECK(HasActiveSession(session_key)); |
| (...skipping 191 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 566 | 607 |
| 567 bool QuicStreamFactory::HasActiveSession( | 608 bool QuicStreamFactory::HasActiveSession( |
| 568 const QuicSessionKey& session_key) const { | 609 const QuicSessionKey& session_key) const { |
| 569 return ContainsKey(active_sessions_, session_key); | 610 return ContainsKey(active_sessions_, session_key); |
| 570 } | 611 } |
| 571 | 612 |
| 572 int QuicStreamFactory::CreateSession( | 613 int QuicStreamFactory::CreateSession( |
| 573 const HostPortPair& host_port_pair, | 614 const HostPortPair& host_port_pair, |
| 574 bool is_https, | 615 bool is_https, |
| 575 CertVerifier* cert_verifier, | 616 CertVerifier* cert_verifier, |
| 617 scoped_ptr<QuicServerInfo> server_info, |
| 576 const AddressList& address_list, | 618 const AddressList& address_list, |
| 577 const BoundNetLog& net_log, | 619 const BoundNetLog& net_log, |
| 578 QuicClientSession** session) { | 620 QuicClientSession** session) { |
| 579 bool enable_port_selection = enable_port_selection_; | 621 bool enable_port_selection = enable_port_selection_; |
| 580 QuicSessionKey session_key(host_port_pair, is_https); | 622 QuicSessionKey session_key(host_port_pair, is_https); |
| 581 if (enable_port_selection && | 623 if (enable_port_selection && |
| 582 ContainsKey(gone_away_aliases_, session_key)) { | 624 ContainsKey(gone_away_aliases_, session_key)) { |
| 583 // Disable port selection when the server is going away. | 625 // Disable port selection when the server is going away. |
| 584 // There is no point in trying to return to the same server, if | 626 // There is no point in trying to return to the same server, if |
| 585 // that server is no longer handling requests. | 627 // that server is no longer handling requests. |
| (...skipping 59 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 645 if (http_server_properties_) { | 687 if (http_server_properties_) { |
| 646 const HttpServerProperties::NetworkStats* stats = | 688 const HttpServerProperties::NetworkStats* stats = |
| 647 http_server_properties_->GetServerNetworkStats(host_port_pair); | 689 http_server_properties_->GetServerNetworkStats(host_port_pair); |
| 648 if (stats != NULL) { | 690 if (stats != NULL) { |
| 649 config.set_initial_round_trip_time_us(stats->rtt.InMicroseconds(), | 691 config.set_initial_round_trip_time_us(stats->rtt.InMicroseconds(), |
| 650 stats->rtt.InMicroseconds()); | 692 stats->rtt.InMicroseconds()); |
| 651 } | 693 } |
| 652 } | 694 } |
| 653 | 695 |
| 654 *session = new QuicClientSession( | 696 *session = new QuicClientSession( |
| 655 connection, socket.Pass(), writer.Pass(), this, | 697 connection, socket.Pass(), writer.Pass(), this, server_info.Pass(), |
| 656 quic_crypto_client_stream_factory_, host_port_pair.host(), | 698 quic_crypto_client_stream_factory_, host_port_pair.host(), |
| 657 config, crypto_config, net_log.net_log()); | 699 config, crypto_config, net_log.net_log()); |
| 658 all_sessions_.insert(*session); // owning pointer | 700 all_sessions_.insert(*session); // owning pointer |
| 659 if (is_https) { | 701 if (is_https) { |
| 660 crypto_config->SetProofVerifier( | 702 crypto_config->SetProofVerifier( |
| 661 new ProofVerifierChromium(cert_verifier, net_log)); | 703 new ProofVerifierChromium(cert_verifier, net_log)); |
| 662 } | 704 } |
| 663 return OK; | 705 return OK; |
| 664 } | 706 } |
| 665 | 707 |
| (...skipping 17 matching lines...) Expand all Loading... |
| 683 const QuicSessionKey& session_key) { | 725 const QuicSessionKey& session_key) { |
| 684 QuicCryptoClientConfig* crypto_config; | 726 QuicCryptoClientConfig* crypto_config; |
| 685 | 727 |
| 686 if (ContainsKey(all_crypto_configs_, session_key)) { | 728 if (ContainsKey(all_crypto_configs_, session_key)) { |
| 687 crypto_config = all_crypto_configs_[session_key]; | 729 crypto_config = all_crypto_configs_[session_key]; |
| 688 DCHECK(crypto_config); | 730 DCHECK(crypto_config); |
| 689 } else { | 731 } else { |
| 690 // TODO(rtenneti): if two quic_sessions for the same host_port_pair | 732 // TODO(rtenneti): if two quic_sessions for the same host_port_pair |
| 691 // share the same crypto_config, will it cause issues? | 733 // share the same crypto_config, will it cause issues? |
| 692 crypto_config = new QuicCryptoClientConfig(); | 734 crypto_config = new QuicCryptoClientConfig(); |
| 693 if (quic_server_info_factory_) { | |
| 694 QuicCryptoClientConfig::CachedState* cached = | |
| 695 crypto_config->Create(session_key.host_port_pair().host(), | |
| 696 quic_server_info_factory_); | |
| 697 DCHECK(cached); | |
| 698 } | |
| 699 crypto_config->SetDefaults(); | 735 crypto_config->SetDefaults(); |
| 700 all_crypto_configs_[session_key] = crypto_config; | 736 all_crypto_configs_[session_key] = crypto_config; |
| 701 PopulateFromCanonicalConfig(session_key, crypto_config); | 737 PopulateFromCanonicalConfig(session_key, crypto_config); |
| 702 } | 738 } |
| 703 return crypto_config; | 739 return crypto_config; |
| 704 } | 740 } |
| 705 | 741 |
| 706 void QuicStreamFactory::PopulateFromCanonicalConfig( | 742 void QuicStreamFactory::PopulateFromCanonicalConfig( |
| 707 const QuicSessionKey& session_key, | 743 const QuicSessionKey& session_key, |
| 708 QuicCryptoClientConfig* crypto_config) { | 744 QuicCryptoClientConfig* crypto_config) { |
| (...skipping 30 matching lines...) Expand all Loading... |
| 739 // as the initial CachedState for the server_hostname in crypto_config. | 775 // as the initial CachedState for the server_hostname in crypto_config. |
| 740 crypto_config->InitializeFrom(server_hostname, | 776 crypto_config->InitializeFrom(server_hostname, |
| 741 canonical_host_port_pair.host(), | 777 canonical_host_port_pair.host(), |
| 742 canonical_crypto_config); | 778 canonical_crypto_config); |
| 743 // Update canonical version to point at the "most recent" crypto_config. | 779 // Update canonical version to point at the "most recent" crypto_config. |
| 744 canonical_hostname_to_origin_map_[suffix_session_key] = | 780 canonical_hostname_to_origin_map_[suffix_session_key] = |
| 745 canonical_session_key; | 781 canonical_session_key; |
| 746 } | 782 } |
| 747 | 783 |
| 748 } // namespace net | 784 } // namespace net |
| OLD | NEW |