diff options
Diffstat (limited to 'chromium/net/quic/quic_chromium_client_session.cc')
-rw-r--r-- | chromium/net/quic/quic_chromium_client_session.cc | 193 |
1 files changed, 123 insertions, 70 deletions
diff --git a/chromium/net/quic/quic_chromium_client_session.cc b/chromium/net/quic/quic_chromium_client_session.cc index 1abab6ba7af..c30b69fc6c1 100644 --- a/chromium/net/quic/quic_chromium_client_session.cc +++ b/chromium/net/quic/quic_chromium_client_session.cc @@ -4,6 +4,8 @@ #include "net/quic/quic_chromium_client_session.h" +#include <utility> + #include "base/callback_helpers.h" #include "base/location.h" #include "base/metrics/histogram_macros.h" @@ -19,7 +21,7 @@ #include "net/http/transport_security_state.h" #include "net/quic/crypto/proof_verifier_chromium.h" #include "net/quic/crypto/quic_server_info.h" -#include "net/quic/quic_connection_helper.h" +#include "net/quic/quic_chromium_connection_helper.h" #include "net/quic/quic_crypto_client_stream_factory.h" #include "net/quic/quic_server_id.h" #include "net/quic/quic_stream_factory.h" @@ -40,6 +42,11 @@ const int k0RttHandshakeTimeoutMs = 300; // IPv6 packets have an additional 20 bytes of overhead than IPv4 packets. const size_t kAdditionalOverheadForIPv6 = 20; +// Maximum number of Readers that are created for any session due to +// connection migration. A new Reader is created every time this endpoint's +// IP address changes. +const size_t kMaxReadersPerQuicSession = 5; + // Histograms for tracking down the crashes from http://crbug.com/354669 // Note: these values must be kept in sync with the corresponding values in: // tools/metrics/histograms/histograms.xml @@ -106,12 +113,11 @@ scoped_ptr<base::Value> NetLogQuicClientSessionCallback( scoped_ptr<base::DictionaryValue> dict(new base::DictionaryValue()); dict->SetString("host", server_id->host()); dict->SetInteger("port", server_id->port()); - dict->SetBoolean("is_https", server_id->is_https()); dict->SetBoolean("privacy_mode", server_id->privacy_mode() == PRIVACY_MODE_ENABLED); dict->SetBoolean("require_confirmation", require_confirmation); dict->SetInteger("cert_verify_flags", cert_verify_flags); - return dict.Pass(); + return std::move(dict); } } // namespace @@ -124,7 +130,7 @@ QuicChromiumClientSession::StreamRequest::~StreamRequest() { int QuicChromiumClientSession::StreamRequest::StartRequest( const base::WeakPtr<QuicChromiumClientSession>& session, - QuicReliableClientStream** stream, + QuicChromiumClientStream** stream, const CompletionCallback& callback) { session_ = session; stream_ = stream; @@ -144,7 +150,7 @@ void QuicChromiumClientSession::StreamRequest::CancelRequest() { } void QuicChromiumClientSession::StreamRequest::OnRequestCompleteSuccess( - QuicReliableClientStream* stream) { + QuicChromiumClientStream* stream) { session_.reset(); *stream_ = stream; ResetAndReturn(&callback_).Run(OK); @@ -179,34 +185,28 @@ QuicChromiumClientSession::QuicChromiumClientSession( server_id_(server_id), require_confirmation_(false), stream_factory_(stream_factory), - socket_(socket.Pass()), transport_security_state_(transport_security_state), - server_info_(server_info.Pass()), + server_info_(std::move(server_info)), num_total_streams_(0), task_runner_(task_runner), net_log_(BoundNetLog::Make(net_log, NetLog::SOURCE_QUIC_SESSION)), - packet_reader_(socket_.get(), - clock, - this, - yield_after_packets, - yield_after_duration, - net_log_), dns_resolution_end_time_(dns_resolution_end_time), logger_(new QuicConnectionLogger(this, connection_description, - socket_performance_watcher.Pass(), + std::move(socket_performance_watcher), net_log_)), going_away_(false), disabled_reason_(QUIC_DISABLED_NOT), weak_factory_(this) { + sockets_.push_back(std::move(socket)); + packet_readers_.push_back(make_scoped_ptr(new QuicPacketReader( + sockets_.back().get(), clock, this, yield_after_packets, + yield_after_duration, net_log_))); crypto_stream_.reset( - crypto_client_stream_factory - ? crypto_client_stream_factory->CreateQuicCryptoClientStream( - server_id, this, crypto_config) - : new QuicCryptoClientStream( - server_id, this, - new ProofVerifyContextChromium(cert_verify_flags, net_log_), - crypto_config)); + crypto_client_stream_factory->CreateQuicCryptoClientStream( + server_id, this, make_scoped_ptr(new ProofVerifyContextChromium( + cert_verify_flags, net_log_)), + crypto_config)); connection->set_debug_visitor(logger_.get()); net_log_.BeginEvent(NetLog::TYPE_QUIC_SESSION, base::Bind(NetLogQuicClientSessionCallback, &server_id, @@ -274,20 +274,8 @@ QuicChromiumClientSession::~QuicChromiumClientSession() { bool port_selected = stream_factory_->enable_port_selection(); SSLInfo ssl_info; - if (!GetSSLInfo(&ssl_info) || !ssl_info.cert.get()) { - if (port_selected) { - UMA_HISTOGRAM_CUSTOM_COUNTS("Net.QuicSession.ConnectSelectPortForHTTP", - round_trip_handshakes, 0, 3, 4); - } else { - UMA_HISTOGRAM_CUSTOM_COUNTS("Net.QuicSession.ConnectRandomPortForHTTP", - round_trip_handshakes, 0, 3, 4); - if (require_confirmation_) { - UMA_HISTOGRAM_CUSTOM_COUNTS( - "Net.QuicSession.ConnectRandomPortRequiringConfirmationForHTTP", - round_trip_handshakes, 0, 3, 4); - } - } - } else { + // QUIC supports only secure urls. + if (GetSSLInfo(&ssl_info) && ssl_info.cert.get()) { if (port_selected) { UMA_HISTOGRAM_CUSTOM_COUNTS("Net.QuicSession.ConnectSelectPortForHTTPS", round_trip_handshakes, 0, 3, 4); @@ -350,6 +338,13 @@ QuicChromiumClientSession::~QuicChromiumClientSession() { static_cast<base::HistogramBase::Sample>(stats.max_sequence_reordering)); } +void QuicChromiumClientSession::OnHeadersHeadOfLineBlocking( + QuicTime::Delta delta) { + UMA_HISTOGRAM_TIMES( + "Net.QuicSession.HeadersHOLBlockedTime", + base::TimeDelta::FromMicroseconds(delta.ToMicroseconds())); +} + void QuicChromiumClientSession::OnStreamFrame(const QuicStreamFrame& frame) { // Record total number of stream frames. UMA_HISTOGRAM_COUNTS("Net.QuicNumStreamFramesInPacket", 1); @@ -378,7 +373,7 @@ void QuicChromiumClientSession::RemoveObserver(Observer* observer) { int QuicChromiumClientSession::TryCreateStream( StreamRequest* request, - QuicReliableClientStream** stream) { + QuicChromiumClientStream** stream) { if (!crypto_stream_->encryption_established()) { DLOG(DFATAL) << "Encryption not established."; return ERR_CONNECTION_CLOSED; @@ -399,7 +394,7 @@ int QuicChromiumClientSession::TryCreateStream( return ERR_CONNECTION_CLOSED; } - if (GetNumOpenStreams() < get_max_open_streams()) { + if (GetNumOpenOutgoingStreams() < get_max_open_streams()) { *stream = CreateOutgoingReliableStreamImpl(); return OK; } @@ -418,15 +413,15 @@ void QuicChromiumClientSession::CancelRequest(StreamRequest* request) { } } -QuicReliableClientStream* -QuicChromiumClientSession::CreateOutgoingDynamicStream() { +QuicChromiumClientStream* +QuicChromiumClientSession::CreateOutgoingDynamicStream(SpdyPriority priority) { if (!crypto_stream_->encryption_established()) { DVLOG(1) << "Encryption not active so no outgoing stream created."; return nullptr; } - if (GetNumOpenStreams() >= get_max_open_streams()) { + if (GetNumOpenOutgoingStreams() >= get_max_open_streams()) { DVLOG(1) << "Failed to create a new outgoing stream. " - << "Already " << GetNumOpenStreams() << " open."; + << "Already " << GetNumOpenOutgoingStreams() << " open."; return nullptr; } if (goaway_received()) { @@ -441,18 +436,19 @@ QuicChromiumClientSession::CreateOutgoingDynamicStream() { return CreateOutgoingReliableStreamImpl(); } -QuicReliableClientStream* +QuicChromiumClientStream* QuicChromiumClientSession::CreateOutgoingReliableStreamImpl() { DCHECK(connection()->connected()); - QuicReliableClientStream* stream = - new QuicReliableClientStream(GetNextStreamId(), this, net_log_); + QuicChromiumClientStream* stream = + new QuicChromiumClientStream(GetNextOutgoingStreamId(), this, net_log_); ActivateStream(stream); ++num_total_streams_; - UMA_HISTOGRAM_COUNTS("Net.QuicSession.NumOpenStreams", GetNumOpenStreams()); + UMA_HISTOGRAM_COUNTS("Net.QuicSession.NumOpenStreams", + GetNumOpenOutgoingStreams()); // The previous histogram puts 100 in a bucket betweeen 86-113 which does // not shed light on if chrome ever things it has more than 100 streams open. UMA_HISTOGRAM_BOOLEAN("Net.QuicSession.TooManyOpenStreams", - GetNumOpenStreams() > 100); + GetNumOpenOutgoingStreams() > 100); return stream; } @@ -475,7 +471,7 @@ bool QuicChromiumClientSession::GetSSLInfo(SSLInfo* ssl_info) const { // Report the TLS cipher suite that most closely resembles the crypto // parameters of the QUIC connection. QuicTag aead = crypto_stream_->crypto_negotiated_params().aead; - uint16 cipher_suite; + uint16_t cipher_suite; int security_bits; switch (aead) { case kAESG: @@ -486,6 +482,10 @@ bool QuicChromiumClientSession::GetSSLInfo(SSLInfo* ssl_info) const { cipher_suite = 0xcc13; // TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256 security_bits = 256; break; + case kCC20: + cipher_suite = 0xcc13; // TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256 + security_bits = 256; + break; default: NOTREACHED(); return false; @@ -506,6 +506,9 @@ bool QuicChromiumClientSession::GetSSLInfo(SSLInfo* ssl_info) const { ssl_info->security_bits = security_bits; ssl_info->handshake_type = SSLInfo::HANDSHAKE_FULL; ssl_info->pinning_failure_log = pinning_failure_log_; + + ssl_info->UpdateSignedCertificateTimestamps(*ct_verify_result_); + return true; } @@ -562,15 +565,15 @@ bool QuicChromiumClientSession::CanPool(const std::string& hostname, } SSLInfo ssl_info; if (!GetSSLInfo(&ssl_info) || !ssl_info.cert.get()) { - // We can always pool with insecure QUIC sessions. - return true; + NOTREACHED() << "QUIC should always have certificates."; + return false; } return SpdySession::CanPool(transport_security_state_, ssl_info, server_id_.host(), hostname); } -QuicDataStream* QuicChromiumClientSession::CreateIncomingDynamicStream( +QuicSpdyStream* QuicChromiumClientSession::CreateIncomingDynamicStream( QuicStreamId id) { DLOG(ERROR) << "Server push not supported"; return nullptr; @@ -594,7 +597,7 @@ void QuicChromiumClientSession::SendRstStream(QuicStreamId id, } void QuicChromiumClientSession::OnClosedStream() { - if (GetNumOpenStreams() < get_max_open_streams() && + if (GetNumOpenOutgoingStreams() < get_max_open_streams() && !stream_requests_.empty() && crypto_stream_->encryption_established() && !goaway_received() && !going_away_ && connection()->connected()) { StreamRequest* request = stream_requests_.front(); @@ -602,7 +605,7 @@ void QuicChromiumClientSession::OnClosedStream() { request->OnRequestCompleteSuccess(CreateOutgoingReliableStreamImpl()); } - if (GetNumOpenStreams() == 0) { + if (GetNumOpenOutgoingStreams() == 0) { stream_factory_->OnIdleSession(this); } } @@ -664,6 +667,12 @@ void QuicChromiumClientSession::OnCryptoHandshakeEvent( void QuicChromiumClientSession::OnCryptoHandshakeMessageSent( const CryptoHandshakeMessage& message) { logger_->OnCryptoHandshakeMessageSent(message); + + if (message.tag() == kREJ || message.tag() == kSREJ) { + UMA_HISTOGRAM_CUSTOM_COUNTS("Net.QuicSession.RejectLength", + message.GetSerialized().length(), 1000, 10000, + 50); + } } void QuicChromiumClientSession::OnCryptoHandshakeMessageReceived( @@ -676,6 +685,11 @@ void QuicChromiumClientSession::OnGoAway(const QuicGoAwayFrame& frame) { NotifyFactoryOfSessionGoingAway(); } +void QuicChromiumClientSession::OnRstStream(const QuicRstStreamFrame& frame) { + QuicSession::OnRstStream(frame); + OnClosedStream(); +} + void QuicChromiumClientSession::OnConnectionClosed(QuicErrorCode error, bool from_peer) { DCHECK(!connection()->connected()); @@ -701,9 +715,9 @@ void QuicChromiumClientSession::OnConnectionClosed(QuicErrorCode error, if (error == QUIC_CONNECTION_TIMED_OUT) { UMA_HISTOGRAM_COUNTS( "Net.QuicSession.ConnectionClose.NumOpenStreams.TimedOut", - GetNumOpenStreams()); + GetNumOpenOutgoingStreams()); if (IsCryptoHandshakeConfirmed()) { - if (GetNumOpenStreams() > 0) { + if (GetNumOpenOutgoingStreams() > 0) { disabled_reason_ = QUIC_DISABLED_TIMEOUT_WITH_OPEN_STREAMS; UMA_HISTOGRAM_BOOLEAN( "Net.QuicSession.TimedOutWithOpenStreams.HasUnackedPackets", @@ -730,7 +744,7 @@ void QuicChromiumClientSession::OnConnectionClosed(QuicErrorCode error, } else { UMA_HISTOGRAM_COUNTS( "Net.QuicSession.ConnectionClose.NumOpenStreams.HandshakeTimedOut", - GetNumOpenStreams()); + GetNumOpenOutgoingStreams()); UMA_HISTOGRAM_COUNTS( "Net.QuicSession.ConnectionClose.NumTotalStreams.HandshakeTimedOut", num_total_streams_); @@ -761,7 +775,10 @@ void QuicChromiumClientSession::OnConnectionClosed(QuicErrorCode error, if (!callback_.is_null()) { base::ResetAndReturn(&callback_).Run(ERR_QUIC_PROTOCOL_ERROR); } - socket_->Close(); + + for (auto& socket : sockets_) { + socket->Close(); + } QuicSession::OnConnectionClosed(error, from_peer); DCHECK(dynamic_streams().empty()); CloseAllStreams(ERR_UNEXPECTED); @@ -797,15 +814,19 @@ void QuicChromiumClientSession::OnProofVerifyDetailsAvailable( const ProofVerifyDetails& verify_details) { const ProofVerifyDetailsChromium* verify_details_chromium = reinterpret_cast<const ProofVerifyDetailsChromium*>(&verify_details); - CertVerifyResult* result_copy = new CertVerifyResult; - result_copy->CopyFrom(verify_details_chromium->cert_verify_result); - cert_verify_result_.reset(result_copy); + cert_verify_result_.reset(new CertVerifyResult); + cert_verify_result_->CopyFrom(verify_details_chromium->cert_verify_result); pinning_failure_log_ = verify_details_chromium->pinning_failure_log; + scoped_ptr<ct::CTVerifyResult> ct_verify_result_copy( + new ct::CTVerifyResult(verify_details_chromium->ct_verify_result)); + ct_verify_result_ = std::move(ct_verify_result_copy); logger_->OnCertificateVerified(*cert_verify_result_); } void QuicChromiumClientSession::StartReading() { - packet_reader_.StartReading(); + for (auto& packet_reader : packet_readers_) { + packet_reader->StartReading(); + } } void QuicChromiumClientSession::CloseSessionOnError(int error, @@ -837,7 +858,7 @@ void QuicChromiumClientSession::CloseSessionOnErrorInner( CloseAllStreams(net_error); CloseAllObservers(net_error); net_log_.AddEvent(NetLog::TYPE_QUIC_SESSION_CLOSE_ON_ERROR, - NetLog::IntegerCallback("net_error", net_error)); + NetLog::IntCallback("net_error", net_error)); if (connection()->connected()) connection()->CloseConnection(quic_error, false); @@ -848,7 +869,7 @@ void QuicChromiumClientSession::CloseAllStreams(int net_error) { while (!dynamic_streams().empty()) { ReliableQuicStream* stream = dynamic_streams().begin()->second; QuicStreamId id = stream->id(); - static_cast<QuicReliableClientStream*>(stream)->OnError(net_error); + static_cast<QuicChromiumClientStream*>(stream)->OnError(net_error); CloseStream(id); } } @@ -865,7 +886,7 @@ scoped_ptr<base::Value> QuicChromiumClientSession::GetInfoAsValue( const std::set<HostPortPair>& aliases) { scoped_ptr<base::DictionaryValue> dict(new base::DictionaryValue()); dict->SetString("version", QuicVersionToString(connection()->version())); - dict->SetInteger("open_streams", GetNumOpenStreams()); + dict->SetInteger("open_streams", GetNumOpenOutgoingStreams()); scoped_ptr<base::ListValue> stream_list(new base::ListValue()); for (base::hash_map<QuicStreamId, ReliableQuicStream*>::const_iterator it = dynamic_streams().begin(); @@ -873,7 +894,7 @@ scoped_ptr<base::Value> QuicChromiumClientSession::GetInfoAsValue( stream_list->Append( new base::StringValue(base::UintToString(it->second->id()))); } - dict->Set("active_streams", stream_list.Pass()); + dict->Set("active_streams", std::move(stream_list)); dict->SetInteger("total_streams", num_total_streams_); dict->SetString("peer_address", peer_address().ToString()); @@ -891,9 +912,9 @@ scoped_ptr<base::Value> QuicChromiumClientSession::GetInfoAsValue( it != aliases.end(); it++) { alias_list->Append(new base::StringValue(it->ToString())); } - dict->Set("aliases", alias_list.Pass()); + dict->Set("aliases", std::move(alias_list)); - return dict.Pass(); + return std::move(dict); } base::WeakPtr<QuicChromiumClientSession> @@ -901,7 +922,15 @@ QuicChromiumClientSession::GetWeakPtr() { return weak_factory_.GetWeakPtr(); } -void QuicChromiumClientSession::OnReadError(int result) { +void QuicChromiumClientSession::OnReadError( + int result, + const DatagramClientSocket* socket) { + DCHECK(socket != nullptr); + if (socket != GetDefaultSocket()) { + // Ignore read errors from old sockets that are no longer active. + // TODO(jri): Maybe clean up old sockets on error. + return; + } DVLOG(1) << "Closing session on read error: " << result; UMA_HISTOGRAM_SPARSE_SLOWLY("Net.QuicSession.ReadError", -result); NotifyFactoryOfSessionGoingAway(); @@ -934,7 +963,7 @@ void QuicChromiumClientSession::NotifyFactoryOfSessionClosedLater() { RecordUnexpectedNotGoingAway(NOTIFY_FACTORY_OF_SESSION_CLOSED_LATER); going_away_ = true; - DCHECK_EQ(0u, GetNumOpenStreams()); + DCHECK_EQ(0u, GetNumActiveStreams()); DCHECK(!connection()->connected()); base::ThreadTaskRunnerHandle::Get()->PostTask( FROM_HERE, @@ -950,7 +979,7 @@ void QuicChromiumClientSession::NotifyFactoryOfSessionClosed() { RecordUnexpectedNotGoingAway(NOTIFY_FACTORY_OF_SESSION_CLOSED); going_away_ = true; - DCHECK_EQ(0u, GetNumOpenStreams()); + DCHECK_EQ(0u, GetNumActiveStreams()); // Will delete |this|. if (stream_factory_) stream_factory_->OnSessionClosed(this); @@ -967,7 +996,31 @@ void QuicChromiumClientSession::OnConnectTimeout() { // if (stream_factory_) // stream_factory_->OnSessionConnectTimeout(this); // CloseAllStreams(ERR_QUIC_HANDSHAKE_FAILED); - // DCHECK_EQ(0u, GetNumOpenStreams()); + // DCHECK_EQ(0u, GetNumOpenOutgoingStreams()); +} + +bool QuicChromiumClientSession::MigrateToSocket( + scoped_ptr<DatagramClientSocket> socket, + scoped_ptr<QuicPacketReader> reader, + scoped_ptr<QuicPacketWriter> writer) { + DCHECK_EQ(sockets_.size(), packet_readers_.size()); + if (sockets_.size() >= kMaxReadersPerQuicSession) { + return false; + } + // TODO(jri): Make SetQuicPacketWriter take a scoped_ptr. + connection()->SetQuicPacketWriter(writer.release(), /*owns_writer=*/true); + packet_readers_.push_back(std::move(reader)); + sockets_.push_back(std::move(socket)); + StartReading(); + connection()->SendPing(); + return true; +} + +const DatagramClientSocket* QuicChromiumClientSession::GetDefaultSocket() + const { + DCHECK(sockets_.back().get() != nullptr); + // The most recently added socket is the currently active one. + return sockets_.back().get(); } } // namespace net |