| OLD | NEW |
| 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #include "net/quic/quic_stream_factory.h" | 5 #include "net/quic/quic_stream_factory.h" |
| 6 | 6 |
| 7 #include <algorithm> | 7 #include <algorithm> |
| 8 #include <set> | 8 #include <set> |
| 9 | 9 |
| 10 #include "base/location.h" | 10 #include "base/location.h" |
| (...skipping 661 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 672 if (!IsEcdsaSupported()) | 672 if (!IsEcdsaSupported()) |
| 673 crypto_config_.DisableEcdsa(); | 673 crypto_config_.DisableEcdsa(); |
| 674 // When disk cache is used to store the server configs, HttpCache code calls | 674 // When disk cache is used to store the server configs, HttpCache code calls |
| 675 // |set_quic_server_info_factory| if |quic_server_info_factory_| wasn't | 675 // |set_quic_server_info_factory| if |quic_server_info_factory_| wasn't |
| 676 // created. | 676 // created. |
| 677 if (store_server_configs_in_properties_) { | 677 if (store_server_configs_in_properties_) { |
| 678 quic_server_info_factory_.reset( | 678 quic_server_info_factory_.reset( |
| 679 new PropertiesBasedQuicServerInfoFactory(http_server_properties_)); | 679 new PropertiesBasedQuicServerInfoFactory(http_server_properties_)); |
| 680 } | 680 } |
| 681 | 681 |
| 682 if (close_sessions_on_ip_change_) { | 682 if (migrate_sessions_on_net_change_) { |
| 683 NetworkChangeNotifier::AddNetworkObserver(this); |
| 684 } else if (close_sessions_on_ip_change_) { |
| 683 NetworkChangeNotifier::AddIPAddressObserver(this); | 685 NetworkChangeNotifier::AddIPAddressObserver(this); |
| 684 } | 686 } |
| 685 } | 687 } |
| 686 | 688 |
| 687 QuicStreamFactory::~QuicStreamFactory() { | 689 QuicStreamFactory::~QuicStreamFactory() { |
| 688 CloseAllSessions(ERR_ABORTED); | 690 CloseAllSessions(ERR_ABORTED); |
| 689 while (!all_sessions_.empty()) { | 691 while (!all_sessions_.empty()) { |
| 690 delete all_sessions_.begin()->first; | 692 delete all_sessions_.begin()->first; |
| 691 all_sessions_.erase(all_sessions_.begin()); | 693 all_sessions_.erase(all_sessions_.begin()); |
| 692 } | 694 } |
| (...skipping 456 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1149 list->Append(session->GetInfoAsValue(hosts)); | 1151 list->Append(session->GetInfoAsValue(hosts)); |
| 1150 } | 1152 } |
| 1151 } | 1153 } |
| 1152 return list.Pass(); | 1154 return list.Pass(); |
| 1153 } | 1155 } |
| 1154 | 1156 |
| 1155 void QuicStreamFactory::ClearCachedStatesInCryptoConfig() { | 1157 void QuicStreamFactory::ClearCachedStatesInCryptoConfig() { |
| 1156 crypto_config_.ClearCachedStates(); | 1158 crypto_config_.ClearCachedStates(); |
| 1157 } | 1159 } |
| 1158 | 1160 |
| 1161 // We still need OnIPAddressChanged, but not for Android >= L. |
| 1162 // pauljensen: How do we do this? |
| 1159 void QuicStreamFactory::OnIPAddressChanged() { | 1163 void QuicStreamFactory::OnIPAddressChanged() { |
| 1160 CloseAllSessions(ERR_NETWORK_CHANGED); | 1164 CloseAllSessions(ERR_NETWORK_CHANGED); |
| 1161 set_require_confirmation(true); | 1165 set_require_confirmation(true); |
| 1162 } | 1166 } |
| 1163 | 1167 |
| 1168 void QuicStreamFactory::OnNetworkConnected( |
| 1169 NetworkChangeNotifier::NetworkHandle network) { |
| 1170 // Nothing to do. |
| 1171 } |
| 1172 |
| 1173 void QuicStreamFactory::OnNetworkMadeDefault( |
| 1174 NetworkChangeNotifier::NetworkHandle network) { |
| 1175 // Nothing to do. |
| 1176 } |
| 1177 |
| 1178 void QuicStreamFactory::OnNetworkDisconnected( |
| 1179 NetworkChangeNotifier::NetworkHandle network) { |
| 1180 MigrateOrCloseSessions(network); |
| 1181 } |
| 1182 |
| 1183 void QuicStreamFactory::OnNetworkSoonToDisconnect( |
| 1184 NetworkChangeNotifier::NetworkHandle network) { |
| 1185 MigrateOrCloseSessions(network); |
| 1186 } |
| 1187 |
| 1188 void QuicStreamFactory::MigrateOrCloseSessions( |
| 1189 NetworkChangeNotifier::NetworkHandle network) { |
| 1190 // pauljensen: do we need the following "== network" check? |
| 1191 NetworkChangeNotifier::NetworkList network_list; |
| 1192 NetworkChangeNotifier::GetConnectedNetworks(&network_list); |
| 1193 if (network_list.empty() || |
| 1194 (network_list.size() == 1 && network_list[0] == network)) { |
| 1195 CloseAllSessions(ERR_NETWORK_CHANGED); |
| 1196 set_require_confirmation(true); |
| 1197 return; |
| 1198 } |
| 1199 |
| 1200 // Find a new network that old sockets can be migrated to. |
| 1201 // pauljensen: do we need the following "== network" check? |
| 1202 NetworkChangeNotifier::NetworkHandle new_network = |
| 1203 NetworkChangeNotifier::kInvalidNetworkHandle; |
| 1204 for (NetworkChangeNotifier::NetworkHandle n : network_list) { |
| 1205 if (n == network) { |
| 1206 continue; |
| 1207 } |
| 1208 new_network = n; |
| 1209 } |
| 1210 |
| 1211 DCHECK_NE(NetworkChangeNotifier::kInvalidNetworkHandle, new_network); |
| 1212 DCHECK_NE(network, new_network); |
| 1213 |
| 1214 for (QuicStreamFactory::SessionIdMap::iterator it = all_sessions_.begin(); |
| 1215 it != all_sessions_.end(); ++it) { |
| 1216 QuicChromiumClientSession* session = it->first; |
| 1217 QuicServerId server_id = it->second; |
| 1218 |
| 1219 if (session->GetNumOpenStreams() == 0) { |
| 1220 // If idle session, close session |
| 1221 active_sessions_.erase(server_id); |
| 1222 session->CloseSessionOnError(ERR_NETWORK_CHANGED, QUIC_INTERNAL_ERROR); |
| 1223 // } else if (session->current_network() == new_network) { |
| 1224 // @@@ TODO (jri): store network and record in session when |
| 1225 // BindToNetwork() is called. |
| 1226 // If session is already using |network|, move on. |
| 1227 // continue; |
| 1228 } else { |
| 1229 // If session is active, |
| 1230 // (i) make the session GO_AWAY, |
| 1231 // (ii) create a new socket (which should be bound to the new interface), |
| 1232 // (iii) add a new PacketReader to the session to read from new socket, |
| 1233 // (iv) replace the connection's PacketWriter with a new PacketWriter |
| 1234 // that uses the new socket. |
| 1235 set_require_confirmation(true); |
| 1236 OnSessionGoingAway(session); |
| 1237 QuicConnection* connection = session->connection(); |
| 1238 |
| 1239 scoped_ptr<DatagramClientSocket> socket = |
| 1240 CreateDatagramClientSocket(all_sessions_[session], |
| 1241 session->net_log()); |
| 1242 |
| 1243 int rv = ConfigureDatagramClientSocket(socket.get(), |
| 1244 connection->peer_address(), |
| 1245 network); |
| 1246 |
| 1247 if (rv != OK) { |
| 1248 session->CloseSessionOnError(ERR_NETWORK_CHANGED, QUIC_INTERNAL_ERROR); |
| 1249 continue; |
| 1250 } |
| 1251 |
| 1252 if (!session->AddPacketReader(new QuicPacketReader(socket.get(), |
| 1253 clock_.get(), |
| 1254 session, |
| 1255 yield_after_packets_, |
| 1256 yield_after_duration_, |
| 1257 session->net_log()))) { |
| 1258 session->CloseSessionOnError(ERR_NETWORK_CHANGED, QUIC_INTERNAL_ERROR); |
| 1259 continue; |
| 1260 } |
| 1261 |
| 1262 session->StartReading(); |
| 1263 DefaultPacketWriterFactory packet_writer_factory(socket.get()); |
| 1264 connection->SetQuicPacketWriter(packet_writer_factory.Create(connection), |
| 1265 /*owns_writer=*/true); |
| 1266 |
| 1267 session->AddSocket(socket.Pass()); |
| 1268 } |
| 1269 } |
| 1270 } |
| 1271 |
| 1164 void QuicStreamFactory::OnSSLConfigChanged() { | 1272 void QuicStreamFactory::OnSSLConfigChanged() { |
| 1165 CloseAllSessions(ERR_CERT_DATABASE_CHANGED); | 1273 CloseAllSessions(ERR_CERT_DATABASE_CHANGED); |
| 1166 } | 1274 } |
| 1167 | 1275 |
| 1168 void QuicStreamFactory::OnCertAdded(const X509Certificate* cert) { | 1276 void QuicStreamFactory::OnCertAdded(const X509Certificate* cert) { |
| 1169 CloseAllSessions(ERR_CERT_DATABASE_CHANGED); | 1277 CloseAllSessions(ERR_CERT_DATABASE_CHANGED); |
| 1170 } | 1278 } |
| 1171 | 1279 |
| 1172 void QuicStreamFactory::OnCACertChanged(const X509Certificate* cert) { | 1280 void QuicStreamFactory::OnCACertChanged(const X509Certificate* cert) { |
| 1173 // We should flush the sessions if we removed trust from a | 1281 // We should flush the sessions if we removed trust from a |
| 1174 // cert, because a previously trusted server may have become | 1282 // cert, because a previously trusted server may have become |
| 1175 // untrusted. | 1283 // untrusted. |
| 1176 // | 1284 // |
| 1177 // We should not flush the sessions if we added trust to a cert. | 1285 // We should not flush the sessions if we added trust to a cert. |
| 1178 // | 1286 // |
| 1179 // Since the OnCACertChanged method doesn't tell us what | 1287 // Since the OnCACertChanged method doesn't tell us what |
| 1180 // kind of change it is, we have to flush the socket | 1288 // kind of change it is, we have to flush the socket |
| 1181 // pools to be safe. | 1289 // pools to be safe. |
| 1182 CloseAllSessions(ERR_CERT_DATABASE_CHANGED); | 1290 CloseAllSessions(ERR_CERT_DATABASE_CHANGED); |
| 1183 } | 1291 } |
| 1184 | 1292 |
| 1185 bool QuicStreamFactory::HasActiveSession( | 1293 bool QuicStreamFactory::HasActiveSession(const QuicServerId& server_id) const { |
| 1186 const QuicServerId& server_id) const { | |
| 1187 return ContainsKey(active_sessions_, server_id); | 1294 return ContainsKey(active_sessions_, server_id); |
| 1188 } | 1295 } |
| 1189 | 1296 |
| 1190 bool QuicStreamFactory::HasActiveJob(const QuicServerId& key) const { | 1297 bool QuicStreamFactory::HasActiveJob(const QuicServerId& key) const { |
| 1191 return ContainsKey(active_jobs_, key); | 1298 return ContainsKey(active_jobs_, key); |
| 1192 } | 1299 } |
| 1193 | 1300 |
| 1194 int QuicStreamFactory::CreateSession(const QuicServerId& server_id, | 1301 scoped_ptr<DatagramClientSocket> QuicStreamFactory::CreateDatagramClientSocket( |
| 1195 int cert_verify_flags, | 1302 const QuicServerId& server_id, const BoundNetLog& net_log) { |
| 1196 scoped_ptr<QuicServerInfo> server_info, | |
| 1197 const AddressList& address_list, | |
| 1198 base::TimeTicks dns_resolution_end_time, | |
| 1199 const BoundNetLog& net_log, | |
| 1200 QuicChromiumClientSession** session) { | |
| 1201 bool enable_port_selection = enable_port_selection_; | 1303 bool enable_port_selection = enable_port_selection_; |
| 1202 if (enable_port_selection && | 1304 if (enable_port_selection && |
| 1203 ContainsKey(gone_away_aliases_, server_id)) { | 1305 ContainsKey(gone_away_aliases_, server_id)) { |
| 1204 // Disable port selection when the server is going away. | 1306 // Disable port selection when the server is going away. |
| 1205 // There is no point in trying to return to the same server, if | 1307 // There is no point in trying to return to the same server, if |
| 1206 // that server is no longer handling requests. | 1308 // that server is no longer handling requests. |
| 1207 enable_port_selection = false; | 1309 enable_port_selection = false; |
| 1208 gone_away_aliases_.erase(server_id); | 1310 gone_away_aliases_.erase(server_id); |
| 1209 } | 1311 } |
| 1210 | |
| 1211 QuicConnectionId connection_id = random_generator_->RandUint64(); | |
| 1212 IPEndPoint addr = *address_list.begin(); | |
| 1213 scoped_refptr<PortSuggester> port_suggester = | 1312 scoped_refptr<PortSuggester> port_suggester = |
| 1214 new PortSuggester(server_id.host_port_pair(), port_seed_); | 1313 new PortSuggester(server_id.host_port_pair(), port_seed_); |
| 1215 DatagramSocket::BindType bind_type = enable_port_selection ? | 1314 DatagramSocket::BindType bind_type = enable_port_selection ? |
| 1216 DatagramSocket::RANDOM_BIND : // Use our callback. | 1315 DatagramSocket::RANDOM_BIND : // Use our callback. |
| 1217 DatagramSocket::DEFAULT_BIND; // Use OS to randomize. | 1316 DatagramSocket::DEFAULT_BIND; // Use OS to randomize. |
| 1317 |
| 1218 scoped_ptr<DatagramClientSocket> socket( | 1318 scoped_ptr<DatagramClientSocket> socket( |
| 1219 client_socket_factory_->CreateDatagramClientSocket( | 1319 client_socket_factory_->CreateDatagramClientSocket( |
| 1220 bind_type, | 1320 bind_type, |
| 1221 base::Bind(&PortSuggester::SuggestPort, port_suggester), | 1321 base::Bind(&PortSuggester::SuggestPort, port_suggester), |
| 1222 net_log.net_log(), net_log.source())); | 1322 net_log.net_log(), net_log.source())); |
| 1223 | 1323 |
| 1324 UMA_HISTOGRAM_COUNTS("Net.QuicEphemeralPortsSuggested", |
| 1325 port_suggester->call_count()); |
| 1326 if (enable_port_selection) { |
| 1327 DCHECK_LE(1u, port_suggester->call_count()); |
| 1328 } else { |
| 1329 DCHECK_EQ(0u, port_suggester->call_count()); |
| 1330 } |
| 1331 |
| 1332 return socket; |
| 1333 } |
| 1334 |
| 1335 int QuicStreamFactory::ConfigureDatagramClientSocket( |
| 1336 DatagramClientSocket* socket, IPEndPoint addr, |
| 1337 NetworkChangeNotifier::NetworkHandle network) { |
| 1224 if (enable_non_blocking_io_ && | 1338 if (enable_non_blocking_io_ && |
| 1225 client_socket_factory_ == ClientSocketFactory::GetDefaultFactory()) { | 1339 client_socket_factory_ == ClientSocketFactory::GetDefaultFactory()) { |
| 1226 #if defined(OS_WIN) | 1340 #if defined(OS_WIN) |
| 1227 static_cast<UDPClientSocket*>(socket.get())->UseNonBlockingIO(); | 1341 static_cast<UDPClientSocket*>(socket.get())->UseNonBlockingIO(); |
| 1228 #endif | 1342 #endif |
| 1229 } | 1343 } |
| 1230 | 1344 |
| 1231 int rv = socket->Connect(addr); | 1345 // If caller leaves network unspecified, find current default. |
| 1346 int rv; |
| 1347 if (network == NetworkChangeNotifier::kInvalidNetworkHandle) { |
| 1348 rv = socket->BindToDefaultNetwork(); |
| 1349 } else { |
| 1350 rv = socket->BindToNetwork(network); |
| 1351 } |
| 1352 if (rv != OK) { |
| 1353 return rv; |
| 1354 } |
| 1232 | 1355 |
| 1356 rv = socket->Connect(addr); |
| 1233 if (rv != OK) { | 1357 if (rv != OK) { |
| 1234 HistogramCreateSessionFailure(CREATION_ERROR_CONNECTING_SOCKET); | 1358 HistogramCreateSessionFailure(CREATION_ERROR_CONNECTING_SOCKET); |
| 1235 return rv; | 1359 return rv; |
| 1236 } | 1360 } |
| 1237 UMA_HISTOGRAM_COUNTS("Net.QuicEphemeralPortsSuggested", | |
| 1238 port_suggester->call_count()); | |
| 1239 if (enable_port_selection) { | |
| 1240 DCHECK_LE(1u, port_suggester->call_count()); | |
| 1241 } else { | |
| 1242 DCHECK_EQ(0u, port_suggester->call_count()); | |
| 1243 } | |
| 1244 | 1361 |
| 1245 rv = socket->SetReceiveBufferSize(socket_receive_buffer_size_); | 1362 rv = socket->SetReceiveBufferSize(socket_receive_buffer_size_); |
| 1246 if (rv != OK) { | 1363 if (rv != OK) { |
| 1247 HistogramCreateSessionFailure(CREATION_ERROR_SETTING_RECEIVE_BUFFER); | 1364 HistogramCreateSessionFailure(CREATION_ERROR_SETTING_RECEIVE_BUFFER); |
| 1248 return rv; | 1365 return rv; |
| 1249 } | 1366 } |
| 1367 |
| 1250 // Set a buffer large enough to contain the initial CWND's worth of packet | 1368 // Set a buffer large enough to contain the initial CWND's worth of packet |
| 1251 // to work around the problem with CHLO packets being sent out with the | 1369 // to work around the problem with CHLO packets being sent out with the |
| 1252 // wrong encryption level, when the send buffer is full. | 1370 // wrong encryption level, when the send buffer is full. |
| 1253 rv = socket->SetSendBufferSize(kMaxPacketSize * 20); | 1371 rv = socket->SetSendBufferSize(kMaxPacketSize * 20); |
| 1254 if (rv != OK) { | 1372 if (rv != OK) { |
| 1255 HistogramCreateSessionFailure(CREATION_ERROR_SETTING_SEND_BUFFER); | 1373 HistogramCreateSessionFailure(CREATION_ERROR_SETTING_SEND_BUFFER); |
| 1256 return rv; | 1374 return rv; |
| 1257 } | 1375 } |
| 1258 | 1376 |
| 1259 socket->GetLocalAddress(&local_address_); | 1377 socket->GetLocalAddress(&local_address_); |
| 1260 if (check_persisted_supports_quic_) { | 1378 if (check_persisted_supports_quic_) { |
| 1261 check_persisted_supports_quic_ = false; | 1379 check_persisted_supports_quic_ = false; |
| 1262 IPAddressNumber last_address; | 1380 IPAddressNumber last_address; |
| 1263 if (http_server_properties_->GetSupportsQuic(&last_address) && | 1381 if (http_server_properties_->GetSupportsQuic(&last_address) && |
| 1264 last_address == local_address_.address()) { | 1382 last_address == local_address_.address()) { |
| 1265 require_confirmation_ = false; | 1383 require_confirmation_ = false; |
| 1266 } | 1384 } |
| 1267 } | 1385 } |
| 1268 | 1386 |
| 1387 return OK; |
| 1388 } |
| 1389 |
| 1390 int QuicStreamFactory::CreateSession(const QuicServerId& server_id, |
| 1391 int cert_verify_flags, |
| 1392 scoped_ptr<QuicServerInfo> server_info, |
| 1393 const AddressList& address_list, |
| 1394 base::TimeTicks dns_resolution_end_time, |
| 1395 const BoundNetLog& net_log, |
| 1396 QuicChromiumClientSession** session) { |
| 1397 IPEndPoint addr = *address_list.begin(); |
| 1398 |
| 1399 scoped_ptr<DatagramClientSocket> socket = |
| 1400 CreateDatagramClientSocket(server_id, net_log); |
| 1401 |
| 1402 int rv = ConfigureDatagramClientSocket(socket.get(), addr, |
| 1403 NetworkChangeNotifier::kInvalidNetworkHandle); |
| 1404 |
| 1405 if (rv != OK) { |
| 1406 return rv; |
| 1407 } |
| 1408 |
| 1269 DefaultPacketWriterFactory packet_writer_factory(socket.get()); | 1409 DefaultPacketWriterFactory packet_writer_factory(socket.get()); |
| 1270 | |
| 1271 if (!helper_.get()) { | 1410 if (!helper_.get()) { |
| 1272 helper_.reset( | 1411 helper_.reset( |
| 1273 new QuicConnectionHelper(base::ThreadTaskRunnerHandle::Get().get(), | 1412 new QuicConnectionHelper(base::ThreadTaskRunnerHandle::Get().get(), |
| 1274 clock_.get(), random_generator_)); | 1413 clock_.get(), random_generator_)); |
| 1275 } | 1414 } |
| 1276 | 1415 |
| 1416 QuicConnectionId connection_id = random_generator_->RandUint64(); |
| 1277 QuicConnection* connection = new QuicConnection( | 1417 QuicConnection* connection = new QuicConnection( |
| 1278 connection_id, addr, helper_.get(), packet_writer_factory, | 1418 connection_id, addr, helper_.get(), packet_writer_factory, |
| 1279 true /* owns_writer */, Perspective::IS_CLIENT, server_id.is_https(), | 1419 true /* owns_writer */, Perspective::IS_CLIENT, server_id.is_https(), |
| 1280 supported_versions_); | 1420 supported_versions_); |
| 1281 connection->SetMaxPacketLength(max_packet_length_); | 1421 connection->SetMaxPacketLength(max_packet_length_); |
| 1282 | 1422 |
| 1283 InitializeCachedStateInCryptoConfig(server_id, server_info); | 1423 InitializeCachedStateInCryptoConfig(server_id, server_info); |
| 1284 | 1424 |
| 1285 QuicConfig config = config_; | 1425 QuicConfig config = config_; |
| 1286 config.SetSocketReceiveBufferToSend(socket_receive_buffer_size_); | 1426 config.SetSocketReceiveBufferToSend(socket_receive_buffer_size_); |
| (...skipping 191 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1478 // Since the session was active, there's no longer an | 1618 // Since the session was active, there's no longer an |
| 1479 // HttpStreamFactoryImpl::Job running which can mark it broken, unless the TCP | 1619 // HttpStreamFactoryImpl::Job running which can mark it broken, unless the TCP |
| 1480 // job also fails. So to avoid not using QUIC when we otherwise could, we mark | 1620 // job also fails. So to avoid not using QUIC when we otherwise could, we mark |
| 1481 // it as recently broken, which means that 0-RTT will be disabled but we'll | 1621 // it as recently broken, which means that 0-RTT will be disabled but we'll |
| 1482 // still race. | 1622 // still race. |
| 1483 http_server_properties_->MarkAlternativeServiceRecentlyBroken( | 1623 http_server_properties_->MarkAlternativeServiceRecentlyBroken( |
| 1484 alternative_service); | 1624 alternative_service); |
| 1485 } | 1625 } |
| 1486 | 1626 |
| 1487 } // namespace net | 1627 } // namespace net |
| OLD | NEW |