| Index: net/quic/quic_chromium_client_session.cc
|
| diff --git a/net/quic/quic_chromium_client_session.cc b/net/quic/quic_chromium_client_session.cc
|
| index 5cb497882bdb426a8b887cf5d216536708bfece4..a44b1dc9ec64ce376941a5c730f6d7f48cd41208 100644
|
| --- a/net/quic/quic_chromium_client_session.cc
|
| +++ b/net/quic/quic_chromium_client_session.cc
|
| @@ -42,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
|
| @@ -180,18 +185,11 @@ QuicChromiumClientSession::QuicChromiumClientSession(
|
| server_id_(server_id),
|
| require_confirmation_(false),
|
| stream_factory_(stream_factory),
|
| - socket_(std::move(socket)),
|
| transport_security_state_(transport_security_state),
|
| 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,
|
| @@ -200,6 +198,10 @@ QuicChromiumClientSession::QuicChromiumClientSession(
|
| 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->CreateQuicCryptoClientStream(
|
| server_id, this, make_scoped_ptr(new ProofVerifyContextChromium(
|
| @@ -773,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);
|
| @@ -819,7 +824,9 @@ void QuicChromiumClientSession::OnProofVerifyDetailsAvailable(
|
| }
|
|
|
| void QuicChromiumClientSession::StartReading() {
|
| - packet_reader_.StartReading();
|
| + for (auto& packet_reader : packet_readers_) {
|
| + packet_reader->StartReading();
|
| + }
|
| }
|
|
|
| void QuicChromiumClientSession::CloseSessionOnError(int error,
|
| @@ -918,6 +925,12 @@ QuicChromiumClientSession::GetWeakPtr() {
|
| 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();
|
| @@ -986,4 +999,28 @@ void QuicChromiumClientSession::OnConnectTimeout() {
|
| // 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(/*force=*/true);
|
| + 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
|
|
|