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_crypto_client_stream.h" | 5 #include "net/quic/quic_crypto_client_stream.h" |
6 | 6 |
7 #include "base/metrics/histogram.h" | 7 #include "base/metrics/histogram.h" |
8 #include "net/base/completion_callback.h" | 8 #include "net/base/completion_callback.h" |
9 #include "net/base/net_errors.h" | 9 #include "net/base/net_errors.h" |
10 #include "net/quic/crypto/crypto_protocol.h" | 10 #include "net/quic/crypto/crypto_protocol.h" |
(...skipping 47 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
58 stream_->DoHandshakeLoop(NULL); | 58 stream_->DoHandshakeLoop(NULL); |
59 | 59 |
60 // The ProofVerifier owns this object and will delete it when this method | 60 // The ProofVerifier owns this object and will delete it when this method |
61 // returns. | 61 // returns. |
62 } | 62 } |
63 | 63 |
64 void QuicCryptoClientStream::ProofVerifierCallbackImpl::Cancel() { | 64 void QuicCryptoClientStream::ProofVerifierCallbackImpl::Cancel() { |
65 stream_ = NULL; | 65 stream_ = NULL; |
66 } | 66 } |
67 | 67 |
68 | |
69 QuicCryptoClientStream::QuicCryptoClientStream( | 68 QuicCryptoClientStream::QuicCryptoClientStream( |
70 const string& server_hostname, | 69 const string& server_hostname, |
71 QuicSession* session, | 70 QuicSession* session, |
72 QuicCryptoClientConfig* crypto_config) | 71 QuicCryptoClientConfig* crypto_config) |
73 : QuicCryptoStream(session), | 72 : QuicCryptoStream(session), |
74 next_state_(STATE_IDLE), | 73 next_state_(STATE_IDLE), |
75 num_client_hellos_(0), | 74 num_client_hellos_(0), |
76 crypto_config_(crypto_config), | 75 crypto_config_(crypto_config), |
77 server_hostname_(server_hostname), | 76 server_hostname_(server_hostname), |
78 generation_counter_(0), | 77 generation_counter_(0), |
(...skipping 192 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
271 &crypto_negotiated_params_, &error_details); | 270 &crypto_negotiated_params_, &error_details); |
272 if (error != QUIC_NO_ERROR) { | 271 if (error != QUIC_NO_ERROR) { |
273 CloseConnectionWithDetails(error, error_details); | 272 CloseConnectionWithDetails(error, error_details); |
274 return; | 273 return; |
275 } | 274 } |
276 if (!cached->proof_valid()) { | 275 if (!cached->proof_valid()) { |
277 ProofVerifier* verifier = crypto_config_->proof_verifier(); | 276 ProofVerifier* verifier = crypto_config_->proof_verifier(); |
278 if (!verifier) { | 277 if (!verifier) { |
279 // If no verifier is set then we don't check the certificates. | 278 // If no verifier is set then we don't check the certificates. |
280 cached->SetProofValid(); | 279 cached->SetProofValid(); |
| 280 SaveQuicServerInfo(*cached); |
281 } else if (!cached->signature().empty()) { | 281 } else if (!cached->signature().empty()) { |
282 next_state_ = STATE_VERIFY_PROOF; | 282 next_state_ = STATE_VERIFY_PROOF; |
283 break; | 283 break; |
284 } | 284 } |
285 } | 285 } |
286 next_state_ = STATE_SEND_CHLO; | 286 next_state_ = STATE_SEND_CHLO; |
287 break; | 287 break; |
288 case STATE_VERIFY_PROOF: { | 288 case STATE_VERIFY_PROOF: { |
289 ProofVerifier* verifier = crypto_config_->proof_verifier(); | 289 ProofVerifier* verifier = crypto_config_->proof_verifier(); |
290 DCHECK(verifier); | 290 DCHECK(verifier); |
(...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
325 QUIC_PROOF_INVALID, "Proof invalid: " + verify_error_details_); | 325 QUIC_PROOF_INVALID, "Proof invalid: " + verify_error_details_); |
326 return; | 326 return; |
327 } | 327 } |
328 // Check if generation_counter has changed between STATE_VERIFY_PROOF | 328 // Check if generation_counter has changed between STATE_VERIFY_PROOF |
329 // and STATE_VERIFY_PROOF_COMPLETE state changes. | 329 // and STATE_VERIFY_PROOF_COMPLETE state changes. |
330 if (generation_counter_ != cached->generation_counter()) { | 330 if (generation_counter_ != cached->generation_counter()) { |
331 next_state_ = STATE_VERIFY_PROOF; | 331 next_state_ = STATE_VERIFY_PROOF; |
332 } else { | 332 } else { |
333 cached->SetProofValid(); | 333 cached->SetProofValid(); |
334 cached->SetProofVerifyDetails(verify_details_.release()); | 334 cached->SetProofVerifyDetails(verify_details_.release()); |
| 335 SaveQuicServerInfo(*cached); |
335 next_state_ = STATE_SEND_CHLO; | 336 next_state_ = STATE_SEND_CHLO; |
336 } | 337 } |
337 break; | 338 break; |
338 case STATE_RECV_SHLO: { | 339 case STATE_RECV_SHLO: { |
339 // We sent a CHLO that we expected to be accepted and now we're hoping | 340 // We sent a CHLO that we expected to be accepted and now we're hoping |
340 // for a SHLO from the server to confirm that. | 341 // for a SHLO from the server to confirm that. |
341 if (in->tag() == kREJ) { | 342 if (in->tag() == kREJ) { |
342 // alternative_decrypter will be NULL if the original alternative | 343 // alternative_decrypter will be NULL if the original alternative |
343 // decrypter latched and became the primary decrypter. That happens | 344 // decrypter latched and became the primary decrypter. That happens |
344 // if we received a message encrypted with the INITIAL key. | 345 // if we received a message encrypted with the INITIAL key. |
(...skipping 63 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
408 } | 409 } |
409 } | 410 } |
410 | 411 |
411 void QuicCryptoClientStream::OnIOComplete(int result) { | 412 void QuicCryptoClientStream::OnIOComplete(int result) { |
412 DCHECK_EQ(STATE_LOAD_QUIC_SERVER_INFO_COMPLETE, next_state_); | 413 DCHECK_EQ(STATE_LOAD_QUIC_SERVER_INFO_COMPLETE, next_state_); |
413 DCHECK_NE(ERR_IO_PENDING, result); | 414 DCHECK_NE(ERR_IO_PENDING, result); |
414 disk_cache_load_result_ = result; | 415 disk_cache_load_result_ = result; |
415 DoHandshakeLoop(NULL); | 416 DoHandshakeLoop(NULL); |
416 } | 417 } |
417 | 418 |
| 419 void QuicCryptoClientStream::SetQuicServerInfo( |
| 420 scoped_ptr<QuicServerInfo> server_info) { |
| 421 quic_server_info_.reset(server_info.release()); |
| 422 } |
| 423 |
418 int QuicCryptoClientStream::DoLoadQuicServerInfo( | 424 int QuicCryptoClientStream::DoLoadQuicServerInfo( |
419 QuicCryptoClientConfig::CachedState* cached) { | 425 QuicCryptoClientConfig::CachedState* cached) { |
420 next_state_ = STATE_SEND_CHLO; | 426 next_state_ = STATE_SEND_CHLO; |
421 QuicServerInfo* quic_server_info = cached->quic_server_info(); | 427 if (!quic_server_info_) { |
422 if (!quic_server_info) { | |
423 return OK; | 428 return OK; |
424 } | 429 } |
425 | 430 |
426 disk_cache_load_start_time_ = base::TimeTicks::Now(); | 431 disk_cache_load_start_time_ = base::TimeTicks::Now(); |
427 generation_counter_ = cached->generation_counter(); | 432 generation_counter_ = cached->generation_counter(); |
428 next_state_ = STATE_LOAD_QUIC_SERVER_INFO_COMPLETE; | 433 next_state_ = STATE_LOAD_QUIC_SERVER_INFO_COMPLETE; |
429 | 434 |
430 // TODO(rtenneti): Use host:port to access QUIC server information from disk | 435 // TODO(rtenneti): Use host:port to access QUIC server information from disk |
431 // cache. If multiple tabs load URLs with same hostname but different | 436 // cache. If multiple tabs load URLs with same hostname but different |
432 // ports, all requests except for the first request send InchoateClientHello. | 437 // ports, all requests except for the first request send InchoateClientHello. |
433 // Fix the code to handle multiple requests. A possible solution is to wait | 438 // Fix the code to handle multiple requests. A possible solution is to wait |
434 // for the first request to finish and use the data from the disk cache for | 439 // for the first request to finish and use the data from the disk cache for |
435 // all requests. | 440 // all requests. |
436 // We may need to call quic_server_info->Persist later. | 441 // We may need to call quic_server_info->Persist later. |
437 // quic_server_info->Persist requires quic_server_info to be ready, so we | 442 // quic_server_info->Persist requires quic_server_info to be ready, so we |
438 // always call WaitForDataReady, even though we might have initialized | 443 // always call WaitForDataReady, even though we might have initialized |
439 // |cached| config from the cached state for a canonical hostname. | 444 // |cached| config from the cached state for a canonical hostname. |
440 int rv = quic_server_info->WaitForDataReady( | 445 int rv = quic_server_info_->WaitForDataReady( |
441 base::Bind(&QuicCryptoClientStream::OnIOComplete, | 446 base::Bind(&QuicCryptoClientStream::OnIOComplete, |
442 weak_factory_.GetWeakPtr())); | 447 weak_factory_.GetWeakPtr())); |
443 | 448 |
444 if (rv != ERR_IO_PENDING) { | 449 if (rv != ERR_IO_PENDING) { |
445 disk_cache_load_result_ = rv; | 450 disk_cache_load_result_ = rv; |
446 } | 451 } |
447 return rv; | 452 return rv; |
448 } | 453 } |
449 | 454 |
450 void QuicCryptoClientStream::DoLoadQuicServerInfoComplete( | 455 void QuicCryptoClientStream::DoLoadQuicServerInfoComplete( |
451 QuicCryptoClientConfig::CachedState* cached) { | 456 QuicCryptoClientConfig::CachedState* cached) { |
452 LoadQuicServerInfo(cached); | 457 LoadQuicServerInfo(cached); |
453 QuicServerInfo::State* state = cached->quic_server_info()->mutable_state(); | 458 QuicServerInfo::State* state = quic_server_info_->mutable_state(); |
454 state->Clear(); | 459 state->Clear(); |
455 } | 460 } |
456 | 461 |
457 void QuicCryptoClientStream::LoadQuicServerInfo( | 462 void QuicCryptoClientStream::LoadQuicServerInfo( |
458 QuicCryptoClientConfig::CachedState* cached) { | 463 QuicCryptoClientConfig::CachedState* cached) { |
459 next_state_ = STATE_SEND_CHLO; | 464 next_state_ = STATE_SEND_CHLO; |
460 | 465 |
461 // If someone else already saved a server config, we don't want to overwrite | 466 // If someone else already saved a server config, we don't want to overwrite |
462 // it. Also, if someone else saved a server config and then cleared it (so | 467 // it. Also, if someone else saved a server config and then cleared it (so |
463 // cached->IsEmpty() is true), we still want to load from QuicServerInfo. | 468 // cached->IsEmpty() is true), we still want to load from QuicServerInfo. |
464 if (!cached->IsEmpty()) { | 469 if (!cached->IsEmpty()) { |
465 return; | 470 return; |
466 } | 471 } |
467 | 472 |
468 UMA_HISTOGRAM_TIMES("Net.QuicServerInfo.DiskCacheReadTime", | 473 UMA_HISTOGRAM_TIMES("Net.QuicServerInfo.DiskCacheReadTime", |
469 base::TimeTicks::Now() - disk_cache_load_start_time_); | 474 base::TimeTicks::Now() - disk_cache_load_start_time_); |
470 | 475 |
471 if (disk_cache_load_result_ != OK || !cached->LoadQuicServerInfo( | 476 if (disk_cache_load_result_ != OK || |
472 session()->connection()->clock()->WallNow())) { | 477 !cached->Initialize(quic_server_info_->state().server_config, |
| 478 quic_server_info_->state().source_address_token, |
| 479 quic_server_info_->state().certs, |
| 480 quic_server_info_->state().server_config_sig, |
| 481 session()->connection()->clock()->WallNow())) { |
473 // It is ok to proceed to STATE_SEND_CHLO when we cannot load QuicServerInfo | 482 // It is ok to proceed to STATE_SEND_CHLO when we cannot load QuicServerInfo |
474 // from the disk cache. | 483 // from the disk cache. |
475 DCHECK(cached->IsEmpty()); | 484 DCHECK(cached->IsEmpty()); |
476 DVLOG(1) << "Empty server_config"; | 485 DVLOG(1) << "Empty server_config"; |
477 return; | 486 return; |
478 } | 487 } |
479 | 488 |
480 ProofVerifier* verifier = crypto_config_->proof_verifier(); | 489 ProofVerifier* verifier = crypto_config_->proof_verifier(); |
481 if (!verifier) { | 490 if (!verifier) { |
482 // If no verifier is set then we don't check the certificates. | 491 // If no verifier is set then we don't check the certificates. |
483 cached->SetProofValid(); | 492 cached->SetProofValid(); |
| 493 SaveQuicServerInfo(*cached); |
484 } else if (!cached->signature().empty()) { | 494 } else if (!cached->signature().empty()) { |
485 next_state_ = STATE_VERIFY_PROOF; | 495 next_state_ = STATE_VERIFY_PROOF; |
486 } | 496 } |
487 } | 497 } |
488 | 498 |
| 499 void QuicCryptoClientStream::SaveQuicServerInfo( |
| 500 const QuicCryptoClientConfig::CachedState& cached) { |
| 501 DCHECK(cached.proof_valid()); |
| 502 |
| 503 // If the QuicServerInfo hasn't managed to load from disk yet then we can't |
| 504 // save anything. TODO(rtenneti): we should fix this. |
| 505 if (!quic_server_info_ || !quic_server_info_->IsDataReady()) { |
| 506 return; |
| 507 } |
| 508 |
| 509 QuicServerInfo::State* state = quic_server_info_->mutable_state(); |
| 510 |
| 511 state->server_config = cached.server_config(); |
| 512 state->source_address_token = cached.source_address_token(); |
| 513 state->server_config_sig = cached.signature(); |
| 514 state->certs = cached.certs(); |
| 515 |
| 516 quic_server_info_->Persist(); |
| 517 } |
| 518 |
489 } // namespace net | 519 } // namespace net |
OLD | NEW |