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 5c9a75115dd11216140b40c9e9ff234c693e1963..ce6c648d6942ab7cf10dcb3c976f9038293d0c1c 100644 |
--- a/net/quic/quic_chromium_client_session.cc |
+++ b/net/quic/quic_chromium_client_session.cc |
@@ -40,6 +40,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 |
@@ -178,18 +183,11 @@ 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()), |
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, |
@@ -198,6 +196,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 |
? crypto_client_stream_factory->CreateQuicCryptoClientStream( |
@@ -770,7 +772,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); |
@@ -816,7 +821,9 @@ void QuicChromiumClientSession::OnProofVerifyDetailsAvailable( |
} |
void QuicChromiumClientSession::StartReading() { |
- packet_reader_.StartReading(); |
+ for (auto& packet_reader : packet_readers_) { |
+ packet_reader->StartReading(); |
+ } |
} |
void QuicChromiumClientSession::CloseSessionOnError(int error, |
@@ -915,6 +922,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(); |
@@ -983,4 +996,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(); |
+ 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 |