| 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/cpu.h" | 9 #include "base/cpu.h" |
| 10 #include "base/message_loop/message_loop.h" | 10 #include "base/message_loop/message_loop.h" |
| (...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 50 CREATION_ERROR_CONNECTING_SOCKET, | 50 CREATION_ERROR_CONNECTING_SOCKET, |
| 51 CREATION_ERROR_SETTING_RECEIVE_BUFFER, | 51 CREATION_ERROR_SETTING_RECEIVE_BUFFER, |
| 52 CREATION_ERROR_SETTING_SEND_BUFFER, | 52 CREATION_ERROR_SETTING_SEND_BUFFER, |
| 53 CREATION_ERROR_MAX | 53 CREATION_ERROR_MAX |
| 54 }; | 54 }; |
| 55 | 55 |
| 56 // The initial receive window size for both streams and sessions. | 56 // The initial receive window size for both streams and sessions. |
| 57 const int32 kInitialReceiveWindowSize = 10 * 1024 * 1024; // 10MB | 57 const int32 kInitialReceiveWindowSize = 10 * 1024 * 1024; // 10MB |
| 58 | 58 |
| 59 void HistogramCreateSessionFailure(enum CreateSessionFailure error) { | 59 void HistogramCreateSessionFailure(enum CreateSessionFailure error) { |
| 60 UMA_HISTOGRAM_ENUMERATION("Net.QuicSession.CreationError", error, | 60 UMA_HISTOGRAM_ENUMERATION( |
| 61 CREATION_ERROR_MAX); | 61 "Net.QuicSession.CreationError", error, CREATION_ERROR_MAX); |
| 62 } | 62 } |
| 63 | 63 |
| 64 bool IsEcdsaSupported() { | 64 bool IsEcdsaSupported() { |
| 65 #if defined(OS_WIN) | 65 #if defined(OS_WIN) |
| 66 if (base::win::GetVersion() < base::win::VERSION_VISTA) | 66 if (base::win::GetVersion() < base::win::VERSION_VISTA) |
| 67 return false; | 67 return false; |
| 68 #endif | 68 #endif |
| 69 | 69 |
| 70 return true; | 70 return true; |
| 71 } | 71 } |
| 72 | 72 |
| 73 } // namespace | 73 } // namespace |
| 74 | 74 |
| 75 QuicStreamFactory::IpAliasKey::IpAliasKey() {} | 75 QuicStreamFactory::IpAliasKey::IpAliasKey() { |
| 76 } |
| 76 | 77 |
| 77 QuicStreamFactory::IpAliasKey::IpAliasKey(IPEndPoint ip_endpoint, | 78 QuicStreamFactory::IpAliasKey::IpAliasKey(IPEndPoint ip_endpoint, bool is_https) |
| 78 bool is_https) | 79 : ip_endpoint(ip_endpoint), is_https(is_https) { |
| 79 : ip_endpoint(ip_endpoint), | 80 } |
| 80 is_https(is_https) {} | |
| 81 | 81 |
| 82 QuicStreamFactory::IpAliasKey::~IpAliasKey() {} | 82 QuicStreamFactory::IpAliasKey::~IpAliasKey() { |
| 83 } |
| 83 | 84 |
| 84 bool QuicStreamFactory::IpAliasKey::operator<( | 85 bool QuicStreamFactory::IpAliasKey::operator<( |
| 85 const QuicStreamFactory::IpAliasKey& other) const { | 86 const QuicStreamFactory::IpAliasKey& other) const { |
| 86 if (!(ip_endpoint == other.ip_endpoint)) { | 87 if (!(ip_endpoint == other.ip_endpoint)) { |
| 87 return ip_endpoint < other.ip_endpoint; | 88 return ip_endpoint < other.ip_endpoint; |
| 88 } | 89 } |
| 89 return is_https < other.is_https; | 90 return is_https < other.is_https; |
| 90 } | 91 } |
| 91 | 92 |
| 92 bool QuicStreamFactory::IpAliasKey::operator==( | 93 bool QuicStreamFactory::IpAliasKey::operator==( |
| 93 const QuicStreamFactory::IpAliasKey& other) const { | 94 const QuicStreamFactory::IpAliasKey& other) const { |
| 94 return is_https == other.is_https && | 95 return is_https == other.is_https && ip_endpoint == other.ip_endpoint; |
| 95 ip_endpoint == other.ip_endpoint; | |
| 96 }; | 96 }; |
| 97 | 97 |
| 98 // Responsible for creating a new QUIC session to the specified server, and | 98 // Responsible for creating a new QUIC session to the specified server, and |
| 99 // for notifying any associated requests when complete. | 99 // for notifying any associated requests when complete. |
| 100 class QuicStreamFactory::Job { | 100 class QuicStreamFactory::Job { |
| 101 public: | 101 public: |
| 102 Job(QuicStreamFactory* factory, | 102 Job(QuicStreamFactory* factory, |
| 103 HostResolver* host_resolver, | 103 HostResolver* host_resolver, |
| 104 const HostPortPair& host_port_pair, | 104 const HostPortPair& host_port_pair, |
| 105 bool is_https, | 105 bool is_https, |
| (...skipping 10 matching lines...) Expand all Loading... |
| 116 int DoLoop(int rv); | 116 int DoLoop(int rv); |
| 117 int DoResolveHost(); | 117 int DoResolveHost(); |
| 118 int DoResolveHostComplete(int rv); | 118 int DoResolveHostComplete(int rv); |
| 119 int DoLoadServerInfo(); | 119 int DoLoadServerInfo(); |
| 120 int DoLoadServerInfoComplete(int rv); | 120 int DoLoadServerInfoComplete(int rv); |
| 121 int DoConnect(); | 121 int DoConnect(); |
| 122 int DoConnectComplete(int rv); | 122 int DoConnectComplete(int rv); |
| 123 | 123 |
| 124 void OnIOComplete(int rv); | 124 void OnIOComplete(int rv); |
| 125 | 125 |
| 126 CompletionCallback callback() { | 126 CompletionCallback callback() { return callback_; } |
| 127 return callback_; | |
| 128 } | |
| 129 | 127 |
| 130 const QuicServerId server_id() const { | 128 const QuicServerId server_id() const { return server_id_; } |
| 131 return server_id_; | |
| 132 } | |
| 133 | 129 |
| 134 private: | 130 private: |
| 135 enum IoState { | 131 enum IoState { |
| 136 STATE_NONE, | 132 STATE_NONE, |
| 137 STATE_RESOLVE_HOST, | 133 STATE_RESOLVE_HOST, |
| 138 STATE_RESOLVE_HOST_COMPLETE, | 134 STATE_RESOLVE_HOST_COMPLETE, |
| 139 STATE_LOAD_SERVER_INFO, | 135 STATE_LOAD_SERVER_INFO, |
| 140 STATE_LOAD_SERVER_INFO_COMPLETE, | 136 STATE_LOAD_SERVER_INFO_COMPLETE, |
| 141 STATE_CONNECT, | 137 STATE_CONNECT, |
| 142 STATE_CONNECT_COMPLETE, | 138 STATE_CONNECT_COMPLETE, |
| (...skipping 26 matching lines...) Expand all Loading... |
| 169 const BoundNetLog& net_log) | 165 const BoundNetLog& net_log) |
| 170 : factory_(factory), | 166 : factory_(factory), |
| 171 host_resolver_(host_resolver), | 167 host_resolver_(host_resolver), |
| 172 server_id_(host_port_pair, is_https, privacy_mode), | 168 server_id_(host_port_pair, is_https, privacy_mode), |
| 173 is_post_(method == "POST"), | 169 is_post_(method == "POST"), |
| 174 was_alternate_protocol_recently_broken_( | 170 was_alternate_protocol_recently_broken_( |
| 175 was_alternate_protocol_recently_broken), | 171 was_alternate_protocol_recently_broken), |
| 176 server_info_(server_info), | 172 server_info_(server_info), |
| 177 net_log_(net_log), | 173 net_log_(net_log), |
| 178 session_(NULL), | 174 session_(NULL), |
| 179 weak_factory_(this) {} | 175 weak_factory_(this) { |
| 176 } |
| 180 | 177 |
| 181 QuicStreamFactory::Job::~Job() { | 178 QuicStreamFactory::Job::~Job() { |
| 182 } | 179 } |
| 183 | 180 |
| 184 int QuicStreamFactory::Job::Run(const CompletionCallback& callback) { | 181 int QuicStreamFactory::Job::Run(const CompletionCallback& callback) { |
| 185 io_state_ = STATE_RESOLVE_HOST; | 182 io_state_ = STATE_RESOLVE_HOST; |
| 186 int rv = DoLoop(OK); | 183 int rv = DoLoop(OK); |
| 187 if (rv == ERR_IO_PENDING) | 184 if (rv == ERR_IO_PENDING) |
| 188 callback_ = callback; | 185 callback_ = callback; |
| 189 | 186 |
| (...skipping 74 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 264 io_state_ = STATE_LOAD_SERVER_INFO; | 261 io_state_ = STATE_LOAD_SERVER_INFO; |
| 265 return OK; | 262 return OK; |
| 266 } | 263 } |
| 267 | 264 |
| 268 int QuicStreamFactory::Job::DoLoadServerInfo() { | 265 int QuicStreamFactory::Job::DoLoadServerInfo() { |
| 269 io_state_ = STATE_LOAD_SERVER_INFO_COMPLETE; | 266 io_state_ = STATE_LOAD_SERVER_INFO_COMPLETE; |
| 270 | 267 |
| 271 if (!server_info_) | 268 if (!server_info_) |
| 272 return OK; | 269 return OK; |
| 273 | 270 |
| 274 return server_info_->WaitForDataReady( | 271 return server_info_->WaitForDataReady(base::Bind( |
| 275 base::Bind(&QuicStreamFactory::Job::OnIOComplete, | 272 &QuicStreamFactory::Job::OnIOComplete, weak_factory_.GetWeakPtr())); |
| 276 weak_factory_.GetWeakPtr())); | |
| 277 } | 273 } |
| 278 | 274 |
| 279 int QuicStreamFactory::Job::DoLoadServerInfoComplete(int rv) { | 275 int QuicStreamFactory::Job::DoLoadServerInfoComplete(int rv) { |
| 280 if (server_info_) { | 276 if (server_info_) { |
| 281 UMA_HISTOGRAM_TIMES("Net.QuicServerInfo.DiskCacheReadTime", | 277 UMA_HISTOGRAM_TIMES("Net.QuicServerInfo.DiskCacheReadTime", |
| 282 base::TimeTicks::Now() - disk_cache_load_start_time_); | 278 base::TimeTicks::Now() - disk_cache_load_start_time_); |
| 283 } | 279 } |
| 284 | 280 |
| 285 if (rv != OK) { | 281 if (rv != OK) { |
| 286 server_info_.reset(); | 282 server_info_.reset(); |
| 287 } | 283 } |
| 288 | 284 |
| 289 io_state_ = STATE_CONNECT; | 285 io_state_ = STATE_CONNECT; |
| 290 return OK; | 286 return OK; |
| 291 } | 287 } |
| 292 | 288 |
| 293 int QuicStreamFactory::Job::DoConnect() { | 289 int QuicStreamFactory::Job::DoConnect() { |
| 294 io_state_ = STATE_CONNECT_COMPLETE; | 290 io_state_ = STATE_CONNECT_COMPLETE; |
| 295 | 291 |
| 296 int rv = factory_->CreateSession(server_id_, server_info_.Pass(), | 292 int rv = factory_->CreateSession( |
| 297 address_list_, net_log_, &session_); | 293 server_id_, server_info_.Pass(), address_list_, net_log_, &session_); |
| 298 if (rv != OK) { | 294 if (rv != OK) { |
| 299 DCHECK(rv != ERR_IO_PENDING); | 295 DCHECK(rv != ERR_IO_PENDING); |
| 300 DCHECK(!session_); | 296 DCHECK(!session_); |
| 301 return rv; | 297 return rv; |
| 302 } | 298 } |
| 303 | 299 |
| 304 session_->StartReading(); | 300 session_->StartReading(); |
| 305 if (!session_->connection()->connected()) { | 301 if (!session_->connection()->connected()) { |
| 306 return ERR_QUIC_PROTOCOL_ERROR; | 302 return ERR_QUIC_PROTOCOL_ERROR; |
| 307 } | 303 } |
| 308 bool require_confirmation = | 304 bool require_confirmation = factory_->require_confirmation() || |
| 309 factory_->require_confirmation() || server_id_.is_https() || is_post_ || | 305 server_id_.is_https() || is_post_ || |
| 310 was_alternate_protocol_recently_broken_; | 306 was_alternate_protocol_recently_broken_; |
| 311 rv = session_->CryptoConnect( | 307 rv = session_->CryptoConnect(require_confirmation, |
| 312 require_confirmation, | 308 base::Bind(&QuicStreamFactory::Job::OnIOComplete, |
| 313 base::Bind(&QuicStreamFactory::Job::OnIOComplete, | 309 base::Unretained(this))); |
| 314 base::Unretained(this))); | |
| 315 return rv; | 310 return rv; |
| 316 } | 311 } |
| 317 | 312 |
| 318 int QuicStreamFactory::Job::DoConnectComplete(int rv) { | 313 int QuicStreamFactory::Job::DoConnectComplete(int rv) { |
| 319 if (rv != OK) | 314 if (rv != OK) |
| 320 return rv; | 315 return rv; |
| 321 | 316 |
| 322 DCHECK(!factory_->HasActiveSession(server_id_)); | 317 DCHECK(!factory_->HasActiveSession(server_id_)); |
| 323 // There may well now be an active session for this IP. If so, use the | 318 // There may well now be an active session for this IP. If so, use the |
| 324 // existing session instead. | 319 // existing session instead. |
| 325 AddressList address(session_->connection()->peer_address()); | 320 AddressList address(session_->connection()->peer_address()); |
| 326 if (factory_->OnResolution(server_id_, address)) { | 321 if (factory_->OnResolution(server_id_, address)) { |
| 327 session_->connection()->SendConnectionClose(QUIC_NO_ERROR); | 322 session_->connection()->SendConnectionClose(QUIC_NO_ERROR); |
| 328 session_ = NULL; | 323 session_ = NULL; |
| 329 return OK; | 324 return OK; |
| 330 } | 325 } |
| 331 | 326 |
| 332 factory_->ActivateSession(server_id_, session_); | 327 factory_->ActivateSession(server_id_, session_); |
| 333 | 328 |
| 334 return OK; | 329 return OK; |
| 335 } | 330 } |
| 336 | 331 |
| 337 QuicStreamRequest::QuicStreamRequest(QuicStreamFactory* factory) | 332 QuicStreamRequest::QuicStreamRequest(QuicStreamFactory* factory) |
| 338 : factory_(factory) {} | 333 : factory_(factory) { |
| 334 } |
| 339 | 335 |
| 340 QuicStreamRequest::~QuicStreamRequest() { | 336 QuicStreamRequest::~QuicStreamRequest() { |
| 341 if (factory_ && !callback_.is_null()) | 337 if (factory_ && !callback_.is_null()) |
| 342 factory_->CancelRequest(this); | 338 factory_->CancelRequest(this); |
| 343 } | 339 } |
| 344 | 340 |
| 345 int QuicStreamRequest::Request(const HostPortPair& host_port_pair, | 341 int QuicStreamRequest::Request(const HostPortPair& host_port_pair, |
| 346 bool is_https, | 342 bool is_https, |
| 347 PrivacyMode privacy_mode, | 343 PrivacyMode privacy_mode, |
| 348 base::StringPiece method, | 344 base::StringPiece method, |
| 349 const BoundNetLog& net_log, | 345 const BoundNetLog& net_log, |
| 350 const CompletionCallback& callback) { | 346 const CompletionCallback& callback) { |
| 351 DCHECK(!stream_); | 347 DCHECK(!stream_); |
| 352 DCHECK(callback_.is_null()); | 348 DCHECK(callback_.is_null()); |
| 353 DCHECK(factory_); | 349 DCHECK(factory_); |
| 354 int rv = factory_->Create(host_port_pair, is_https, privacy_mode, method, | 350 int rv = factory_->Create( |
| 355 net_log, this); | 351 host_port_pair, is_https, privacy_mode, method, net_log, this); |
| 356 if (rv == ERR_IO_PENDING) { | 352 if (rv == ERR_IO_PENDING) { |
| 357 host_port_pair_ = host_port_pair; | 353 host_port_pair_ = host_port_pair; |
| 358 is_https_ = is_https; | 354 is_https_ = is_https; |
| 359 net_log_ = net_log; | 355 net_log_ = net_log; |
| 360 callback_ = callback; | 356 callback_ = callback; |
| 361 } else { | 357 } else { |
| 362 factory_ = NULL; | 358 factory_ = NULL; |
| 363 } | 359 } |
| 364 if (rv == OK) | 360 if (rv == OK) |
| 365 DCHECK(stream_); | 361 DCHECK(stream_); |
| (...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 406 max_packet_length_(max_packet_length), | 402 max_packet_length_(max_packet_length), |
| 407 supported_versions_(supported_versions), | 403 supported_versions_(supported_versions), |
| 408 enable_port_selection_(enable_port_selection), | 404 enable_port_selection_(enable_port_selection), |
| 409 enable_pacing_(enable_pacing), | 405 enable_pacing_(enable_pacing), |
| 410 port_seed_(random_generator_->RandUint64()), | 406 port_seed_(random_generator_->RandUint64()), |
| 411 weak_factory_(this) { | 407 weak_factory_(this) { |
| 412 config_.SetDefaults(); | 408 config_.SetDefaults(); |
| 413 config_.EnablePacing(enable_pacing_); | 409 config_.EnablePacing(enable_pacing_); |
| 414 if (enable_time_based_loss_detection) | 410 if (enable_time_based_loss_detection) |
| 415 config_.SetLossDetectionToSend(kTIME); | 411 config_.SetLossDetectionToSend(kTIME); |
| 416 config_.set_idle_connection_state_lifetime( | 412 config_.set_idle_connection_state_lifetime(QuicTime::Delta::FromSeconds(30), |
| 417 QuicTime::Delta::FromSeconds(30), | 413 QuicTime::Delta::FromSeconds(30)); |
| 418 QuicTime::Delta::FromSeconds(30)); | |
| 419 | 414 |
| 420 crypto_config_.SetDefaults(); | 415 crypto_config_.SetDefaults(); |
| 421 crypto_config_.AddCanonicalSuffix(".c.youtube.com"); | 416 crypto_config_.AddCanonicalSuffix(".c.youtube.com"); |
| 422 crypto_config_.AddCanonicalSuffix(".googlevideo.com"); | 417 crypto_config_.AddCanonicalSuffix(".googlevideo.com"); |
| 423 crypto_config_.SetProofVerifier(new ProofVerifierChromium(cert_verifier)); | 418 crypto_config_.SetProofVerifier(new ProofVerifierChromium(cert_verifier)); |
| 424 base::CPU cpu; | 419 base::CPU cpu; |
| 425 if (cpu.has_aesni() && cpu.has_avx()) | 420 if (cpu.has_aesni() && cpu.has_avx()) |
| 426 crypto_config_.PreferAesGcm(); | 421 crypto_config_.PreferAesGcm(); |
| 427 if (!IsEcdsaSupported()) | 422 if (!IsEcdsaSupported()) |
| 428 crypto_config_.DisableEcdsa(); | 423 crypto_config_.DisableEcdsa(); |
| (...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 462 crypto_config_.LookupOrCreate(server_id); | 457 crypto_config_.LookupOrCreate(server_id); |
| 463 DCHECK(cached); | 458 DCHECK(cached); |
| 464 if (cached->IsEmpty()) { | 459 if (cached->IsEmpty()) { |
| 465 quic_server_info = quic_server_info_factory_->GetForServer(server_id); | 460 quic_server_info = quic_server_info_factory_->GetForServer(server_id); |
| 466 } | 461 } |
| 467 } | 462 } |
| 468 bool was_alternate_protocol_recently_broken = | 463 bool was_alternate_protocol_recently_broken = |
| 469 http_server_properties_ && | 464 http_server_properties_ && |
| 470 http_server_properties_->WasAlternateProtocolRecentlyBroken( | 465 http_server_properties_->WasAlternateProtocolRecentlyBroken( |
| 471 server_id.host_port_pair()); | 466 server_id.host_port_pair()); |
| 472 scoped_ptr<Job> job(new Job(this, host_resolver_, host_port_pair, is_https, | 467 scoped_ptr<Job> job(new Job(this, |
| 468 host_resolver_, |
| 469 host_port_pair, |
| 470 is_https, |
| 473 was_alternate_protocol_recently_broken, | 471 was_alternate_protocol_recently_broken, |
| 474 privacy_mode, method, quic_server_info, net_log)); | 472 privacy_mode, |
| 475 int rv = job->Run(base::Bind(&QuicStreamFactory::OnJobComplete, | 473 method, |
| 476 base::Unretained(this), job.get())); | 474 quic_server_info, |
| 475 net_log)); |
| 476 int rv = job->Run(base::Bind( |
| 477 &QuicStreamFactory::OnJobComplete, base::Unretained(this), job.get())); |
| 477 | 478 |
| 478 if (rv == ERR_IO_PENDING) { | 479 if (rv == ERR_IO_PENDING) { |
| 479 active_requests_[request] = job.get(); | 480 active_requests_[request] = job.get(); |
| 480 job_requests_map_[job.get()].insert(request); | 481 job_requests_map_[job.get()].insert(request); |
| 481 active_jobs_[server_id] = job.release(); | 482 active_jobs_[server_id] = job.release(); |
| 482 } | 483 } |
| 483 if (rv == OK) { | 484 if (rv == OK) { |
| 484 DCHECK(HasActiveSession(server_id)); | 485 DCHECK(HasActiveSession(server_id)); |
| 485 request->set_stream(CreateIfSessionExists(server_id, net_log)); | 486 request->set_stream(CreateIfSessionExists(server_id, net_log)); |
| 486 } | 487 } |
| 487 return rv; | 488 return rv; |
| 488 } | 489 } |
| 489 | 490 |
| 490 bool QuicStreamFactory::OnResolution( | 491 bool QuicStreamFactory::OnResolution(const QuicServerId& server_id, |
| 491 const QuicServerId& server_id, | 492 const AddressList& address_list) { |
| 492 const AddressList& address_list) { | |
| 493 DCHECK(!HasActiveSession(server_id)); | 493 DCHECK(!HasActiveSession(server_id)); |
| 494 for (size_t i = 0; i < address_list.size(); ++i) { | 494 for (size_t i = 0; i < address_list.size(); ++i) { |
| 495 const IPEndPoint& address = address_list[i]; | 495 const IPEndPoint& address = address_list[i]; |
| 496 const IpAliasKey ip_alias_key(address, server_id.is_https()); | 496 const IpAliasKey ip_alias_key(address, server_id.is_https()); |
| 497 if (!ContainsKey(ip_aliases_, ip_alias_key)) | 497 if (!ContainsKey(ip_aliases_, ip_alias_key)) |
| 498 continue; | 498 continue; |
| 499 | 499 |
| 500 const SessionSet& sessions = ip_aliases_[ip_alias_key]; | 500 const SessionSet& sessions = ip_aliases_[ip_alias_key]; |
| 501 for (SessionSet::const_iterator i = sessions.begin(); | 501 for (SessionSet::const_iterator i = sessions.begin(); i != sessions.end(); |
| 502 i != sessions.end(); ++i) { | 502 ++i) { |
| 503 QuicClientSession* session = *i; | 503 QuicClientSession* session = *i; |
| 504 if (!session->CanPool(server_id.host())) | 504 if (!session->CanPool(server_id.host())) |
| 505 continue; | 505 continue; |
| 506 active_sessions_[server_id] = session; | 506 active_sessions_[server_id] = session; |
| 507 session_aliases_[session].insert(server_id); | 507 session_aliases_[session].insert(server_id); |
| 508 return true; | 508 return true; |
| 509 } | 509 } |
| 510 } | 510 } |
| 511 return false; | 511 return false; |
| 512 } | 512 } |
| 513 | 513 |
| 514 void QuicStreamFactory::OnJobComplete(Job* job, int rv) { | 514 void QuicStreamFactory::OnJobComplete(Job* job, int rv) { |
| 515 if (rv == OK) { | 515 if (rv == OK) { |
| 516 require_confirmation_ = false; | 516 require_confirmation_ = false; |
| 517 | 517 |
| 518 // Create all the streams, but do not notify them yet. | 518 // Create all the streams, but do not notify them yet. |
| 519 for (RequestSet::iterator it = job_requests_map_[job].begin(); | 519 for (RequestSet::iterator it = job_requests_map_[job].begin(); |
| 520 it != job_requests_map_[job].end() ; ++it) { | 520 it != job_requests_map_[job].end(); |
| 521 ++it) { |
| 521 DCHECK(HasActiveSession(job->server_id())); | 522 DCHECK(HasActiveSession(job->server_id())); |
| 522 (*it)->set_stream(CreateIfSessionExists(job->server_id(), | 523 (*it)->set_stream( |
| 523 (*it)->net_log())); | 524 CreateIfSessionExists(job->server_id(), (*it)->net_log())); |
| 524 } | 525 } |
| 525 } | 526 } |
| 526 while (!job_requests_map_[job].empty()) { | 527 while (!job_requests_map_[job].empty()) { |
| 527 RequestSet::iterator it = job_requests_map_[job].begin(); | 528 RequestSet::iterator it = job_requests_map_[job].begin(); |
| 528 QuicStreamRequest* request = *it; | 529 QuicStreamRequest* request = *it; |
| 529 job_requests_map_[job].erase(it); | 530 job_requests_map_[job].erase(it); |
| 530 active_requests_.erase(request); | 531 active_requests_.erase(request); |
| 531 // Even though we're invoking callbacks here, we don't need to worry | 532 // Even though we're invoking callbacks here, we don't need to worry |
| 532 // about |this| being deleted, because the factory is owned by the | 533 // about |this| being deleted, because the factory is owned by the |
| 533 // profile which can not be deleted via callbacks. | 534 // profile which can not be deleted via callbacks. |
| (...skipping 10 matching lines...) Expand all Loading... |
| 544 scoped_ptr<QuicHttpStream> QuicStreamFactory::CreateIfSessionExists( | 545 scoped_ptr<QuicHttpStream> QuicStreamFactory::CreateIfSessionExists( |
| 545 const QuicServerId& server_id, | 546 const QuicServerId& server_id, |
| 546 const BoundNetLog& net_log) { | 547 const BoundNetLog& net_log) { |
| 547 if (!HasActiveSession(server_id)) { | 548 if (!HasActiveSession(server_id)) { |
| 548 DVLOG(1) << "No active session"; | 549 DVLOG(1) << "No active session"; |
| 549 return scoped_ptr<QuicHttpStream>(); | 550 return scoped_ptr<QuicHttpStream>(); |
| 550 } | 551 } |
| 551 | 552 |
| 552 QuicClientSession* session = active_sessions_[server_id]; | 553 QuicClientSession* session = active_sessions_[server_id]; |
| 553 DCHECK(session); | 554 DCHECK(session); |
| 554 return scoped_ptr<QuicHttpStream>( | 555 return scoped_ptr<QuicHttpStream>(new QuicHttpStream(session->GetWeakPtr())); |
| 555 new QuicHttpStream(session->GetWeakPtr())); | |
| 556 } | 556 } |
| 557 | 557 |
| 558 void QuicStreamFactory::OnIdleSession(QuicClientSession* session) { | 558 void QuicStreamFactory::OnIdleSession(QuicClientSession* session) { |
| 559 } | 559 } |
| 560 | 560 |
| 561 void QuicStreamFactory::OnSessionGoingAway(QuicClientSession* session) { | 561 void QuicStreamFactory::OnSessionGoingAway(QuicClientSession* session) { |
| 562 const AliasSet& aliases = session_aliases_[session]; | 562 const AliasSet& aliases = session_aliases_[session]; |
| 563 for (AliasSet::const_iterator it = aliases.begin(); it != aliases.end(); | 563 for (AliasSet::const_iterator it = aliases.begin(); it != aliases.end(); |
| 564 ++it) { | 564 ++it) { |
| 565 DCHECK(active_sessions_.count(*it)); | 565 DCHECK(active_sessions_.count(*it)); |
| (...skipping 44 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 610 all_sessions_.begin()->first->CloseSessionOnError(error); | 610 all_sessions_.begin()->first->CloseSessionOnError(error); |
| 611 DCHECK_NE(initial_size, all_sessions_.size()); | 611 DCHECK_NE(initial_size, all_sessions_.size()); |
| 612 } | 612 } |
| 613 DCHECK(all_sessions_.empty()); | 613 DCHECK(all_sessions_.empty()); |
| 614 } | 614 } |
| 615 | 615 |
| 616 base::Value* QuicStreamFactory::QuicStreamFactoryInfoToValue() const { | 616 base::Value* QuicStreamFactory::QuicStreamFactoryInfoToValue() const { |
| 617 base::ListValue* list = new base::ListValue(); | 617 base::ListValue* list = new base::ListValue(); |
| 618 | 618 |
| 619 for (SessionMap::const_iterator it = active_sessions_.begin(); | 619 for (SessionMap::const_iterator it = active_sessions_.begin(); |
| 620 it != active_sessions_.end(); ++it) { | 620 it != active_sessions_.end(); |
| 621 ++it) { |
| 621 const QuicServerId& server_id = it->first; | 622 const QuicServerId& server_id = it->first; |
| 622 QuicClientSession* session = it->second; | 623 QuicClientSession* session = it->second; |
| 623 const AliasSet& aliases = session_aliases_.find(session)->second; | 624 const AliasSet& aliases = session_aliases_.find(session)->second; |
| 624 // Only add a session to the list once. | 625 // Only add a session to the list once. |
| 625 if (server_id == *aliases.begin()) { | 626 if (server_id == *aliases.begin()) { |
| 626 std::set<HostPortPair> hosts; | 627 std::set<HostPortPair> hosts; |
| 627 for (AliasSet::const_iterator alias_it = aliases.begin(); | 628 for (AliasSet::const_iterator alias_it = aliases.begin(); |
| 628 alias_it != aliases.end(); ++alias_it) { | 629 alias_it != aliases.end(); |
| 630 ++alias_it) { |
| 629 hosts.insert(alias_it->host_port_pair()); | 631 hosts.insert(alias_it->host_port_pair()); |
| 630 } | 632 } |
| 631 list->Append(session->GetInfoAsValue(hosts)); | 633 list->Append(session->GetInfoAsValue(hosts)); |
| 632 } | 634 } |
| 633 } | 635 } |
| 634 return list; | 636 return list; |
| 635 } | 637 } |
| 636 | 638 |
| 637 void QuicStreamFactory::ClearCachedStatesInCryptoConfig() { | 639 void QuicStreamFactory::ClearCachedStatesInCryptoConfig() { |
| 638 crypto_config_.ClearCachedStates(); | 640 crypto_config_.ClearCachedStates(); |
| (...skipping 14 matching lines...) Expand all Loading... |
| 653 // untrusted. | 655 // untrusted. |
| 654 // | 656 // |
| 655 // We should not flush the sessions if we added trust to a cert. | 657 // We should not flush the sessions if we added trust to a cert. |
| 656 // | 658 // |
| 657 // Since the OnCACertChanged method doesn't tell us what | 659 // Since the OnCACertChanged method doesn't tell us what |
| 658 // kind of change it is, we have to flush the socket | 660 // kind of change it is, we have to flush the socket |
| 659 // pools to be safe. | 661 // pools to be safe. |
| 660 CloseAllSessions(ERR_CERT_DATABASE_CHANGED); | 662 CloseAllSessions(ERR_CERT_DATABASE_CHANGED); |
| 661 } | 663 } |
| 662 | 664 |
| 663 bool QuicStreamFactory::HasActiveSession( | 665 bool QuicStreamFactory::HasActiveSession(const QuicServerId& server_id) const { |
| 664 const QuicServerId& server_id) const { | |
| 665 return ContainsKey(active_sessions_, server_id); | 666 return ContainsKey(active_sessions_, server_id); |
| 666 } | 667 } |
| 667 | 668 |
| 668 int QuicStreamFactory::CreateSession( | 669 int QuicStreamFactory::CreateSession(const QuicServerId& server_id, |
| 669 const QuicServerId& server_id, | 670 scoped_ptr<QuicServerInfo> server_info, |
| 670 scoped_ptr<QuicServerInfo> server_info, | 671 const AddressList& address_list, |
| 671 const AddressList& address_list, | 672 const BoundNetLog& net_log, |
| 672 const BoundNetLog& net_log, | 673 QuicClientSession** session) { |
| 673 QuicClientSession** session) { | |
| 674 bool enable_port_selection = enable_port_selection_; | 674 bool enable_port_selection = enable_port_selection_; |
| 675 if (enable_port_selection && | 675 if (enable_port_selection && ContainsKey(gone_away_aliases_, server_id)) { |
| 676 ContainsKey(gone_away_aliases_, server_id)) { | |
| 677 // Disable port selection when the server is going away. | 676 // Disable port selection when the server is going away. |
| 678 // There is no point in trying to return to the same server, if | 677 // There is no point in trying to return to the same server, if |
| 679 // that server is no longer handling requests. | 678 // that server is no longer handling requests. |
| 680 enable_port_selection = false; | 679 enable_port_selection = false; |
| 681 gone_away_aliases_.erase(server_id); | 680 gone_away_aliases_.erase(server_id); |
| 682 } | 681 } |
| 683 | 682 |
| 684 QuicConnectionId connection_id = random_generator_->RandUint64(); | 683 QuicConnectionId connection_id = random_generator_->RandUint64(); |
| 685 IPEndPoint addr = *address_list.begin(); | 684 IPEndPoint addr = *address_list.begin(); |
| 686 scoped_refptr<PortSuggester> port_suggester = | 685 scoped_refptr<PortSuggester> port_suggester = |
| 687 new PortSuggester(server_id.host_port_pair(), port_seed_); | 686 new PortSuggester(server_id.host_port_pair(), port_seed_); |
| 688 DatagramSocket::BindType bind_type = enable_port_selection ? | 687 DatagramSocket::BindType bind_type = |
| 689 DatagramSocket::RANDOM_BIND : // Use our callback. | 688 enable_port_selection ? DatagramSocket::RANDOM_BIND |
| 690 DatagramSocket::DEFAULT_BIND; // Use OS to randomize. | 689 : // Use our callback. |
| 690 DatagramSocket::DEFAULT_BIND; // Use OS to randomize. |
| 691 scoped_ptr<DatagramClientSocket> socket( | 691 scoped_ptr<DatagramClientSocket> socket( |
| 692 client_socket_factory_->CreateDatagramClientSocket( | 692 client_socket_factory_->CreateDatagramClientSocket( |
| 693 bind_type, | 693 bind_type, |
| 694 base::Bind(&PortSuggester::SuggestPort, port_suggester), | 694 base::Bind(&PortSuggester::SuggestPort, port_suggester), |
| 695 net_log.net_log(), net_log.source())); | 695 net_log.net_log(), |
| 696 net_log.source())); |
| 696 int rv = socket->Connect(addr); | 697 int rv = socket->Connect(addr); |
| 697 if (rv != OK) { | 698 if (rv != OK) { |
| 698 HistogramCreateSessionFailure(CREATION_ERROR_CONNECTING_SOCKET); | 699 HistogramCreateSessionFailure(CREATION_ERROR_CONNECTING_SOCKET); |
| 699 return rv; | 700 return rv; |
| 700 } | 701 } |
| 701 UMA_HISTOGRAM_COUNTS("Net.QuicEphemeralPortsSuggested", | 702 UMA_HISTOGRAM_COUNTS("Net.QuicEphemeralPortsSuggested", |
| 702 port_suggester->call_count()); | 703 port_suggester->call_count()); |
| 703 if (enable_port_selection) { | 704 if (enable_port_selection) { |
| 704 DCHECK_LE(1u, port_suggester->call_count()); | 705 DCHECK_LE(1u, port_suggester->call_count()); |
| 705 } else { | 706 } else { |
| (...skipping 18 matching lines...) Expand all Loading... |
| 724 HistogramCreateSessionFailure(CREATION_ERROR_SETTING_SEND_BUFFER); | 725 HistogramCreateSessionFailure(CREATION_ERROR_SETTING_SEND_BUFFER); |
| 725 return rv; | 726 return rv; |
| 726 } | 727 } |
| 727 | 728 |
| 728 scoped_ptr<QuicDefaultPacketWriter> writer( | 729 scoped_ptr<QuicDefaultPacketWriter> writer( |
| 729 new QuicDefaultPacketWriter(socket.get())); | 730 new QuicDefaultPacketWriter(socket.get())); |
| 730 | 731 |
| 731 if (!helper_.get()) { | 732 if (!helper_.get()) { |
| 732 helper_.reset(new QuicConnectionHelper( | 733 helper_.reset(new QuicConnectionHelper( |
| 733 base::MessageLoop::current()->message_loop_proxy().get(), | 734 base::MessageLoop::current()->message_loop_proxy().get(), |
| 734 clock_.get(), random_generator_)); | 735 clock_.get(), |
| 736 random_generator_)); |
| 735 } | 737 } |
| 736 | 738 |
| 737 QuicConnection* connection = | 739 QuicConnection* connection = new QuicConnection(connection_id, |
| 738 new QuicConnection(connection_id, addr, helper_.get(), writer.get(), | 740 addr, |
| 739 false, supported_versions_, kInitialReceiveWindowSize); | 741 helper_.get(), |
| 742 writer.get(), |
| 743 false, |
| 744 supported_versions_, |
| 745 kInitialReceiveWindowSize); |
| 740 writer->SetConnection(connection); | 746 writer->SetConnection(connection); |
| 741 connection->options()->max_packet_length = max_packet_length_; | 747 connection->options()->max_packet_length = max_packet_length_; |
| 742 | 748 |
| 743 InitializeCachedStateInCryptoConfig(server_id, server_info); | 749 InitializeCachedStateInCryptoConfig(server_id, server_info); |
| 744 | 750 |
| 745 QuicConfig config = config_; | 751 QuicConfig config = config_; |
| 746 if (http_server_properties_) { | 752 if (http_server_properties_) { |
| 747 const HttpServerProperties::NetworkStats* stats = | 753 const HttpServerProperties::NetworkStats* stats = |
| 748 http_server_properties_->GetServerNetworkStats( | 754 http_server_properties_->GetServerNetworkStats( |
| 749 server_id.host_port_pair()); | 755 server_id.host_port_pair()); |
| 750 if (stats != NULL) { | 756 if (stats != NULL) { |
| 751 config.SetInitialRoundTripTimeUsToSend(stats->srtt.InMicroseconds()); | 757 config.SetInitialRoundTripTimeUsToSend(stats->srtt.InMicroseconds()); |
| 752 } | 758 } |
| 753 } | 759 } |
| 754 | 760 |
| 755 *session = new QuicClientSession( | 761 *session = new QuicClientSession(connection, |
| 756 connection, socket.Pass(), writer.Pass(), this, | 762 socket.Pass(), |
| 757 quic_crypto_client_stream_factory_, server_info.Pass(), server_id, | 763 writer.Pass(), |
| 758 config, &crypto_config_, net_log.net_log()); | 764 this, |
| 765 quic_crypto_client_stream_factory_, |
| 766 server_info.Pass(), |
| 767 server_id, |
| 768 config, |
| 769 &crypto_config_, |
| 770 net_log.net_log()); |
| 759 all_sessions_[*session] = server_id; // owning pointer | 771 all_sessions_[*session] = server_id; // owning pointer |
| 760 return OK; | 772 return OK; |
| 761 } | 773 } |
| 762 | 774 |
| 763 bool QuicStreamFactory::HasActiveJob(const QuicServerId& key) const { | 775 bool QuicStreamFactory::HasActiveJob(const QuicServerId& key) const { |
| 764 return ContainsKey(active_jobs_, key); | 776 return ContainsKey(active_jobs_, key); |
| 765 } | 777 } |
| 766 | 778 |
| 767 void QuicStreamFactory::ActivateSession( | 779 void QuicStreamFactory::ActivateSession(const QuicServerId& server_id, |
| 768 const QuicServerId& server_id, | 780 QuicClientSession* session) { |
| 769 QuicClientSession* session) { | |
| 770 DCHECK(!HasActiveSession(server_id)); | 781 DCHECK(!HasActiveSession(server_id)); |
| 771 active_sessions_[server_id] = session; | 782 active_sessions_[server_id] = session; |
| 772 session_aliases_[session].insert(server_id); | 783 session_aliases_[session].insert(server_id); |
| 773 const IpAliasKey ip_alias_key(session->connection()->peer_address(), | 784 const IpAliasKey ip_alias_key(session->connection()->peer_address(), |
| 774 server_id.is_https()); | 785 server_id.is_https()); |
| 775 DCHECK(!ContainsKey(ip_aliases_[ip_alias_key], session)); | 786 DCHECK(!ContainsKey(ip_aliases_[ip_alias_key], session)); |
| 776 ip_aliases_[ip_alias_key].insert(session); | 787 ip_aliases_[ip_alias_key].insert(session); |
| 777 } | 788 } |
| 778 | 789 |
| 779 void QuicStreamFactory::InitializeCachedStateInCryptoConfig( | 790 void QuicStreamFactory::InitializeCachedStateInCryptoConfig( |
| (...skipping 13 matching lines...) Expand all Loading... |
| 793 server_info->state().server_config_sig, | 804 server_info->state().server_config_sig, |
| 794 clock_->WallNow())) | 805 clock_->WallNow())) |
| 795 return; | 806 return; |
| 796 | 807 |
| 797 if (!server_id.is_https()) { | 808 if (!server_id.is_https()) { |
| 798 // Don't check the certificates for insecure QUIC. | 809 // Don't check the certificates for insecure QUIC. |
| 799 cached->SetProofValid(); | 810 cached->SetProofValid(); |
| 800 } | 811 } |
| 801 } | 812 } |
| 802 | 813 |
| 803 void QuicStreamFactory::ProcessGoingAwaySession( | 814 void QuicStreamFactory::ProcessGoingAwaySession(QuicClientSession* session, |
| 804 QuicClientSession* session, | 815 const QuicServerId& server_id) { |
| 805 const QuicServerId& server_id) { | |
| 806 if (!http_server_properties_) | 816 if (!http_server_properties_) |
| 807 return; | 817 return; |
| 808 | 818 |
| 809 const QuicConnectionStats& stats = session->connection()->GetStats(); | 819 const QuicConnectionStats& stats = session->connection()->GetStats(); |
| 810 if (!session->IsCryptoHandshakeConfirmed()) { | 820 if (!session->IsCryptoHandshakeConfirmed()) { |
| 811 // TODO(rch): In the special case where the session has received no | 821 // TODO(rch): In the special case where the session has received no |
| 812 // packets from the peer, we should consider blacklisting this | 822 // packets from the peer, we should consider blacklisting this |
| 813 // differently so that we still race TCP but we don't consider the | 823 // differently so that we still race TCP but we don't consider the |
| 814 // session connected until the handshake has been confirmed. | 824 // session connected until the handshake has been confirmed. |
| 815 HistogramBrokenAlternateProtocolLocation( | 825 HistogramBrokenAlternateProtocolLocation( |
| 816 BROKEN_ALTERNATE_PROTOCOL_LOCATION_QUIC_STREAM_FACTORY); | 826 BROKEN_ALTERNATE_PROTOCOL_LOCATION_QUIC_STREAM_FACTORY); |
| 817 http_server_properties_->SetBrokenAlternateProtocol( | 827 http_server_properties_->SetBrokenAlternateProtocol( |
| 818 server_id.host_port_pair()); | 828 server_id.host_port_pair()); |
| 819 UMA_HISTOGRAM_COUNTS("Net.QuicHandshakeNotConfirmedNumPacketsReceived", | 829 UMA_HISTOGRAM_COUNTS("Net.QuicHandshakeNotConfirmedNumPacketsReceived", |
| 820 stats.packets_received); | 830 stats.packets_received); |
| 821 return; | 831 return; |
| 822 } | 832 } |
| 823 | 833 |
| 824 HttpServerProperties::NetworkStats network_stats; | 834 HttpServerProperties::NetworkStats network_stats; |
| 825 network_stats.srtt = base::TimeDelta::FromMicroseconds(stats.srtt_us); | 835 network_stats.srtt = base::TimeDelta::FromMicroseconds(stats.srtt_us); |
| 826 network_stats.bandwidth_estimate = stats.estimated_bandwidth; | 836 network_stats.bandwidth_estimate = stats.estimated_bandwidth; |
| 827 http_server_properties_->SetServerNetworkStats(server_id.host_port_pair(), | 837 http_server_properties_->SetServerNetworkStats(server_id.host_port_pair(), |
| 828 network_stats); | 838 network_stats); |
| 829 } | 839 } |
| 830 | 840 |
| 831 } // namespace net | 841 } // namespace net |
| OLD | NEW |