Index: net/quic/quic_stream_factory.cc |
diff --git a/net/quic/quic_stream_factory.cc b/net/quic/quic_stream_factory.cc |
index 62fd664968e90222bff02d26f3fd20676184ffc9..cab6455116ae3dfe63bfc7a0c088154814e9b3da 100644 |
--- a/net/quic/quic_stream_factory.cc |
+++ b/net/quic/quic_stream_factory.cc |
@@ -56,6 +56,7 @@ |
#endif |
using std::min; |
+using NetworkChangeNotifier::NetworkHandle; |
namespace net { |
@@ -78,6 +79,9 @@ const int32 kQuicStreamMaxRecvWindowSize = 6 * 1024 * 1024; // 6 MB |
// Set the maximum number of undecryptable packets the connection will store. |
const int32 kMaxUndecryptablePackets = 100; |
+// A default NetworkHandle. |
+const NetworkHandle kDefaultNetworkHandle = -2; |
pauljensen
2015/10/14 11:51:34
This is a little sketchy for my liking. I'd sugge
Jana
2015/10/16 23:11:00
I think this is all sketchy :-) But, yeah, it seem
|
+ |
void HistogramCreateSessionFailure(enum CreateSessionFailure error) { |
UMA_HISTOGRAM_ENUMERATION("Net.QuicSession.CreationError", error, |
CREATION_ERROR_MAX); |
@@ -1137,11 +1141,108 @@ void QuicStreamFactory::ClearCachedStatesInCryptoConfig() { |
crypto_config_.ClearCachedStates(); |
} |
+// We still need OnIPAddressChanged, but not for Android >= L. |
+// pauljensen: How do we do this? |
pauljensen
2015/10/14 11:51:34
Where do you register for events? (i.e. call Netwo
Jana
2015/10/16 23:11:00
*Facepalm*. So I discovered that we do not actuall
|
void QuicStreamFactory::OnIPAddressChanged() { |
CloseAllSessions(ERR_NETWORK_CHANGED); |
set_require_confirmation(true); |
} |
+void QuicStreamFactory::OnNetworkConnected(NetworkHandle network) { |
+ // Nothing to do. |
+} |
+ |
+void QuicStreamFactory::OnNetworkMadeDefault(NetworkHandle network) { |
+ // Nothing to do. |
+} |
+ |
+void QuicStreamFactory::OnNetworkDisconnected(NetworkHandle network) { |
+ MigrateOrCloseSessions(network); |
+} |
+ |
+void QuicStreamFactory::OnNetworkSoonToDisconnect(NetworkHandle network) { |
+ MigrateOrCloseSessions(network); |
+} |
+ |
+void QuicStreamFactory::MigrateOrCloseSessions(NetworkHandle network) { |
+ // pauljensen: do we need the following "== network" check? |
pauljensen
2015/10/14 11:51:34
seems like a good idea
Jana
2015/10/16 23:11:00
Acknowledged.
|
+ NetworkList network_list; |
+ GetConnectedNetworks(&network_list); |
+ if (network_list.isEmpty() || |
+ (network_list.size() == 1 && network_list[0] == network)) { |
+ CloseAllSessions(ERR_NETWORK_CHANGED); |
+ set_require_confirmation(true); |
+ return; |
+ } |
+ |
+ // Find a new network that old sockets can be migrated to. |
+ // pauljensen: do we need the following "== network" check? |
pauljensen
2015/10/14 11:51:34
seems like a good idea
Jana
2015/10/16 23:11:00
Acknowledged.
|
+ NetworkHandle new_network = kInvalidNetworkHandle; |
+ for (NetworkHandle n : network_list) { |
+ if (n == network) { |
+ continue; |
+ } |
+ new_network = n; |
+ } |
+ |
+ DCHECK_NE(kInvalidNetworkHandle, new_network); |
+ DCHECK_NE(network, new_network); |
+ |
+ for (QuicStreamFactory::SessionIdMap::iterator it = all_sessions_.begin(); |
+ it != all_sessions_.end(); ++it) { |
+ QuicChromiumClientSession* session = it->first; |
+ QuicServerId server_id = it->second; |
+ |
+ if (session->GetNumOpenStreams() == 0) { |
+ // If idle session, close session |
+ active_sessions_.erase(server_id); |
+ session->CloseSessionOnError(ERR_NETWORK_CHANGED, QUIC_INTERNAL_ERROR); |
+ } else if (session->current_network() == new_network) { |
+ // @@@ TODO (jri): store network and record in session when |
+ // BindToNetwork() is called. |
+ // If session is already using |network|, move on. |
+ continue; |
+ } else { |
+ // If session is active, |
+ // (i) make the session GO_AWAY, |
+ // (ii) create a new socket (which should be bound to the new interface), |
+ // (iii) add a new PacketReader to the session to read from new socket, |
+ // (iv) replace the connection's PacketWriter with a new PacketWriter |
+ // that uses the new socket. |
+ set_require_confirmation(true); |
+ OnSessionGoingAway(session); |
+ scoped_ptr<DatagramClientSocket> socket; |
+ int rv = CreateAndConfigureDatagramSocket(&socket, |
+ all_sessions[*session], |
+ connection->peer_address(), |
+ session->net_log(), |
+ new_network); |
+ if (rv != OK) { |
+ session->CloseSessionOnError(ERR_NETWORK_CHANGED, QUIC_INTERNAL_ERROR); |
+ continue; |
+ } |
+ |
+ if (!session->AddPacketReader(new QuicPacketReader(socket.get(), |
+ clock_.get(), |
+ session, |
+ yield_after_packets_, |
+ yield_after_duration_, |
+ session->net_log()))) { |
+ session->CloseSessionOnError(ERR_NETWORK_CHANGED, QUIC_INTERNAL_ERROR); |
+ continue; |
+ } |
+ |
+ session->StartReading(); |
+ DefaultPacketWriterFactory packet_writer_factory(socket.get()); |
+ QuicConnection* connection = session->connection(); |
+ connection->SetQuicPacketWriter(packet_writer_factory.Create(connection), |
+ /*owns_writer=*/true); |
+ |
+ session->AddSocket(socket.Pass()); |
+ } |
+ } |
+} |
+ |
void QuicStreamFactory::OnSSLConfigChanged() { |
CloseAllSessions(ERR_CERT_DATABASE_CHANGED); |
} |
@@ -1172,13 +1273,12 @@ bool QuicStreamFactory::HasActiveJob(const QuicServerId& key) const { |
return ContainsKey(active_jobs_, key); |
} |
-int QuicStreamFactory::CreateSession(const QuicServerId& server_id, |
- int cert_verify_flags, |
- scoped_ptr<QuicServerInfo> server_info, |
- const AddressList& address_list, |
- base::TimeTicks dns_resolution_end_time, |
- const BoundNetLog& net_log, |
- QuicChromiumClientSession** session) { |
+int QuicStreamFactory::CreateAndConfigureDatagramSocket( |
+ scoped_ptr<DatagramClientSocket>* new_socket, |
pauljensen
2015/10/14 11:51:34
http://dev.chromium.org/developers/smart-pointer-g
Jana
2015/10/16 23:11:00
Done.
|
+ const QuicServerId& server_id, |
+ IPEndPoint addr, |
+ const BoundNetLog& net_log, |
+ NetworkHandle network) { |
bool enable_port_selection = enable_port_selection_; |
if (enable_port_selection && |
ContainsKey(gone_away_aliases_, server_id)) { |
@@ -1189,8 +1289,6 @@ int QuicStreamFactory::CreateSession(const QuicServerId& server_id, |
gone_away_aliases_.erase(server_id); |
} |
- QuicConnectionId connection_id = random_generator_->RandUint64(); |
- IPEndPoint addr = *address_list.begin(); |
scoped_refptr<PortSuggester> port_suggester = |
new PortSuggester(server_id.host_port_pair(), port_seed_); |
DatagramSocket::BindType bind_type = enable_port_selection ? |
@@ -1209,8 +1307,22 @@ int QuicStreamFactory::CreateSession(const QuicServerId& server_id, |
#endif |
} |
- int rv = socket->Connect(addr); |
+ // If caller leaves network unspecified, find current default. |
+ if (network == kDefaultNetworkHandle) { |
+ network = NetworkChangeNotifier::GetDefaultNetwork(); |
pauljensen
2015/10/14 11:51:34
We may want to loop here in cases where the defaul
Jana
2015/10/16 23:11:00
I've added a BindToDefaultNetwork method to Datagr
|
+ if (network == kDefaultNetworkHandle) { |
+ return ERR_INTERNET_DISCONNECTED; |
+ } |
+ } |
+ |
+ new_socket->Reset(socket.get()); |
+ int rv = socket->BindToNetwork(network); |
+ if (rv != OK) { |
+ return rv; |
+ } |
+ |
+ rv = socket->Connect(addr); |
if (rv != OK) { |
HistogramCreateSessionFailure(CREATION_ERROR_CONNECTING_SOCKET); |
return rv; |
@@ -1246,15 +1358,34 @@ int QuicStreamFactory::CreateSession(const QuicServerId& server_id, |
require_confirmation_ = false; |
} |
} |
+ return OK; |
+} |
- DefaultPacketWriterFactory packet_writer_factory(socket.get()); |
+int QuicStreamFactory::CreateSession(const QuicServerId& server_id, |
+ int cert_verify_flags, |
+ scoped_ptr<QuicServerInfo> server_info, |
+ const AddressList& address_list, |
+ base::TimeTicks dns_resolution_end_time, |
+ const BoundNetLog& net_log, |
+ QuicChromiumClientSession** session) { |
+ scoped_ptr<DatagramClientSocket> socket; |
+ int rv = CreateAndConfigureDatagramSocket(&socket, |
+ server_id, |
+ *address_list.begin(), |
+ net_log, |
+ kDefaultNetworkHandle); |
+ if (rv != OK) { |
+ return rv; |
+ } |
+ DefaultPacketWriterFactory packet_writer_factory(socket.get()); |
if (!helper_.get()) { |
helper_.reset( |
new QuicConnectionHelper(base::ThreadTaskRunnerHandle::Get().get(), |
clock_.get(), random_generator_)); |
} |
+ QuicConnectionId connection_id = random_generator_->RandUint64(); |
QuicConnection* connection = new QuicConnection( |
connection_id, addr, helper_.get(), packet_writer_factory, |
true /* owns_writer */, Perspective::IS_CLIENT, server_id.is_https(), |