| Index: net/quic/quic_stream_factory.cc
|
| diff --git a/net/quic/quic_stream_factory.cc b/net/quic/quic_stream_factory.cc
|
| index 858f1cb93f0744e9960bd084dcd0393f8b1b04b4..a5be87e983fe1ffaa7b51c97627220a0470b7cee 100644
|
| --- a/net/quic/quic_stream_factory.cc
|
| +++ b/net/quic/quic_stream_factory.cc
|
| @@ -1183,22 +1183,25 @@ void QuicStreamFactory::OnNetworkSoonToDisconnect(
|
| MaybeMigrateOrCloseSessions(network, /*force_close=*/false);
|
| }
|
|
|
| +NetworkChangeNotifier::NetworkHandle QuicStreamFactory::FindAlternateNetwork(
|
| + NetworkChangeNotifier::NetworkHandle old_network) {
|
| + // Find a new network that sessions bound to |old_network| can be migrated to.
|
| + NetworkChangeNotifier::NetworkList network_list;
|
| + NetworkChangeNotifier::GetConnectedNetworks(&network_list);
|
| + for (NetworkChangeNotifier::NetworkHandle new_network : network_list) {
|
| + if (new_network != old_network) {
|
| + return new_network;
|
| + }
|
| + }
|
| + return NetworkChangeNotifier::kInvalidNetworkHandle;
|
| +}
|
| +
|
| void QuicStreamFactory::MaybeMigrateOrCloseSessions(
|
| NetworkChangeNotifier::NetworkHandle network,
|
| bool force_close) {
|
| DCHECK_NE(NetworkChangeNotifier::kInvalidNetworkHandle, network);
|
| -
|
| - // Find a new network that sessions bound to |network| can be migrated to.
|
| - NetworkChangeNotifier::NetworkList network_list;
|
| - NetworkChangeNotifier::GetConnectedNetworks(&network_list);
|
| NetworkChangeNotifier::NetworkHandle new_network =
|
| - NetworkChangeNotifier::kInvalidNetworkHandle;
|
| - for (NetworkChangeNotifier::NetworkHandle n : network_list) {
|
| - if (n != network) {
|
| - new_network = n;
|
| - break;
|
| - }
|
| - }
|
| + FindAlternateNetwork(network);
|
|
|
| QuicStreamFactory::SessionIdMap::iterator it = all_sessions_.begin();
|
| while (it != all_sessions_.end()) {
|
| @@ -1228,38 +1231,58 @@ void QuicStreamFactory::MaybeMigrateOrCloseSessions(
|
| }
|
| continue;
|
| }
|
| + MigrateSessionToNetwork(session, new_network);
|
| + }
|
| +}
|
|
|
| - // Use OS-specified port for socket (DEFAULT_BIND) instead of
|
| - // using the PortSuggester since the connection is being migrated
|
| - // and not being newly created.
|
| - scoped_ptr<DatagramClientSocket> socket(
|
| - client_socket_factory_->CreateDatagramClientSocket(
|
| - DatagramSocket::DEFAULT_BIND, RandIntCallback(),
|
| - session->net_log().net_log(), session->net_log().source()));
|
| -
|
| - QuicConnection* connection = session->connection();
|
| - if (ConfigureSocket(socket.get(), connection->peer_address(),
|
| - new_network) != OK) {
|
| - session->CloseSessionOnError(ERR_NETWORK_CHANGED, QUIC_INTERNAL_ERROR);
|
| - HistogramMigrationStatus(MIGRATION_STATUS_INTERNAL_ERROR);
|
| - continue;
|
| - }
|
| +void QuicStreamFactory::MaybeMigrateSessionEarly(
|
| + QuicChromiumClientSession* session) {
|
| + if (session->GetNumActiveStreams() == 0) {
|
| + return;
|
| + }
|
| + NetworkChangeNotifier::NetworkHandle current_network =
|
| + session->GetDefaultSocket()->GetBoundNetwork();
|
| + NetworkChangeNotifier::NetworkHandle new_network =
|
| + FindAlternateNetwork(current_network);
|
| + if (new_network == NetworkChangeNotifier::kInvalidNetworkHandle) {
|
| + // No alternate network found.
|
| + return;
|
| + }
|
| + OnSessionGoingAway(session);
|
| + MigrateSessionToNetwork(session, new_network);
|
| +}
|
|
|
| - scoped_ptr<QuicPacketReader> new_reader(new QuicPacketReader(
|
| - socket.get(), clock_.get(), session, yield_after_packets_,
|
| - yield_after_duration_, session->net_log()));
|
| - scoped_ptr<QuicPacketWriter> new_writer(
|
| - new QuicDefaultPacketWriter(socket.get()));
|
| -
|
| - if (!session->MigrateToSocket(std::move(socket), std::move(new_reader),
|
| - std::move(new_writer))) {
|
| - session->CloseSessionOnError(ERR_NETWORK_CHANGED,
|
| - QUIC_CONNECTION_MIGRATION_TOO_MANY_CHANGES);
|
| - HistogramMigrationStatus(MIGRATION_STATUS_TOO_MANY_CHANGES);
|
| - } else {
|
| - HistogramMigrationStatus(MIGRATION_STATUS_SUCCESS);
|
| - }
|
| +void QuicStreamFactory::MigrateSessionToNetwork(
|
| + QuicChromiumClientSession* session,
|
| + NetworkChangeNotifier::NetworkHandle new_network) {
|
| + // Use OS-specified port for socket (DEFAULT_BIND) instead of
|
| + // using the PortSuggester since the connection is being migrated
|
| + // and not being newly created.
|
| + scoped_ptr<DatagramClientSocket> socket(
|
| + client_socket_factory_->CreateDatagramClientSocket(
|
| + DatagramSocket::DEFAULT_BIND, RandIntCallback(),
|
| + session->net_log().net_log(), session->net_log().source()));
|
| + QuicConnection* connection = session->connection();
|
| + if (ConfigureSocket(socket.get(), connection->peer_address(), new_network) !=
|
| + OK) {
|
| + session->CloseSessionOnError(ERR_NETWORK_CHANGED, QUIC_INTERNAL_ERROR);
|
| + HistogramMigrationStatus(MIGRATION_STATUS_INTERNAL_ERROR);
|
| + return;
|
| + }
|
| + scoped_ptr<QuicPacketReader> new_reader(new QuicPacketReader(
|
| + socket.get(), clock_.get(), session, yield_after_packets_,
|
| + yield_after_duration_, session->net_log()));
|
| + scoped_ptr<QuicPacketWriter> new_writer(
|
| + new QuicDefaultPacketWriter(socket.get()));
|
| +
|
| + if (!session->MigrateToSocket(std::move(socket), std::move(new_reader),
|
| + std::move(new_writer))) {
|
| + session->CloseSessionOnError(ERR_NETWORK_CHANGED,
|
| + QUIC_CONNECTION_MIGRATION_TOO_MANY_CHANGES);
|
| + HistogramMigrationStatus(MIGRATION_STATUS_TOO_MANY_CHANGES);
|
| + return;
|
| }
|
| + HistogramMigrationStatus(MIGRATION_STATUS_SUCCESS);
|
| }
|
|
|
| void QuicStreamFactory::OnSSLConfigChanged() {
|
|
|