Chromium Code Reviews| 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 38 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 49 #endif | 49 #endif |
| 50 | 50 |
| 51 #if defined(USE_OPENSSL) | 51 #if defined(USE_OPENSSL) |
| 52 #include <openssl/aead.h> | 52 #include <openssl/aead.h> |
| 53 #include "crypto/openssl_util.h" | 53 #include "crypto/openssl_util.h" |
| 54 #else | 54 #else |
| 55 #include "base/cpu.h" | 55 #include "base/cpu.h" |
| 56 #endif | 56 #endif |
| 57 | 57 |
| 58 using std::min; | 58 using std::min; |
| 59 using NetworkChangeNotifier::NetworkHandle; | |
| 59 | 60 |
| 60 namespace net { | 61 namespace net { |
| 61 | 62 |
| 62 namespace { | 63 namespace { |
| 63 | 64 |
| 64 enum CreateSessionFailure { | 65 enum CreateSessionFailure { |
| 65 CREATION_ERROR_CONNECTING_SOCKET, | 66 CREATION_ERROR_CONNECTING_SOCKET, |
| 66 CREATION_ERROR_SETTING_RECEIVE_BUFFER, | 67 CREATION_ERROR_SETTING_RECEIVE_BUFFER, |
| 67 CREATION_ERROR_SETTING_SEND_BUFFER, | 68 CREATION_ERROR_SETTING_SEND_BUFFER, |
| 68 CREATION_ERROR_MAX | 69 CREATION_ERROR_MAX |
| 69 }; | 70 }; |
| 70 | 71 |
| 71 // When a connection is idle for 30 seconds it will be closed. | 72 // When a connection is idle for 30 seconds it will be closed. |
| 72 const int kIdleConnectionTimeoutSeconds = 30; | 73 const int kIdleConnectionTimeoutSeconds = 30; |
| 73 | 74 |
| 74 // The maximum receive window sizes for QUIC sessions and streams. | 75 // The maximum receive window sizes for QUIC sessions and streams. |
| 75 const int32 kQuicSessionMaxRecvWindowSize = 15 * 1024 * 1024; // 15 MB | 76 const int32 kQuicSessionMaxRecvWindowSize = 15 * 1024 * 1024; // 15 MB |
| 76 const int32 kQuicStreamMaxRecvWindowSize = 6 * 1024 * 1024; // 6 MB | 77 const int32 kQuicStreamMaxRecvWindowSize = 6 * 1024 * 1024; // 6 MB |
| 77 | 78 |
| 78 // Set the maximum number of undecryptable packets the connection will store. | 79 // Set the maximum number of undecryptable packets the connection will store. |
| 79 const int32 kMaxUndecryptablePackets = 100; | 80 const int32 kMaxUndecryptablePackets = 100; |
| 80 | 81 |
| 82 // A default NetworkHandle. | |
| 83 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
| |
| 84 | |
| 81 void HistogramCreateSessionFailure(enum CreateSessionFailure error) { | 85 void HistogramCreateSessionFailure(enum CreateSessionFailure error) { |
| 82 UMA_HISTOGRAM_ENUMERATION("Net.QuicSession.CreationError", error, | 86 UMA_HISTOGRAM_ENUMERATION("Net.QuicSession.CreationError", error, |
| 83 CREATION_ERROR_MAX); | 87 CREATION_ERROR_MAX); |
| 84 } | 88 } |
| 85 | 89 |
| 86 bool IsEcdsaSupported() { | 90 bool IsEcdsaSupported() { |
| 87 #if defined(OS_WIN) | 91 #if defined(OS_WIN) |
| 88 if (base::win::GetVersion() < base::win::VERSION_VISTA) | 92 if (base::win::GetVersion() < base::win::VERSION_VISTA) |
| 89 return false; | 93 return false; |
| 90 #endif | 94 #endif |
| (...skipping 1039 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1130 list->Append(session->GetInfoAsValue(hosts)); | 1134 list->Append(session->GetInfoAsValue(hosts)); |
| 1131 } | 1135 } |
| 1132 } | 1136 } |
| 1133 return list.Pass(); | 1137 return list.Pass(); |
| 1134 } | 1138 } |
| 1135 | 1139 |
| 1136 void QuicStreamFactory::ClearCachedStatesInCryptoConfig() { | 1140 void QuicStreamFactory::ClearCachedStatesInCryptoConfig() { |
| 1137 crypto_config_.ClearCachedStates(); | 1141 crypto_config_.ClearCachedStates(); |
| 1138 } | 1142 } |
| 1139 | 1143 |
| 1144 // We still need OnIPAddressChanged, but not for Android >= L. | |
| 1145 // 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
| |
| 1140 void QuicStreamFactory::OnIPAddressChanged() { | 1146 void QuicStreamFactory::OnIPAddressChanged() { |
| 1141 CloseAllSessions(ERR_NETWORK_CHANGED); | 1147 CloseAllSessions(ERR_NETWORK_CHANGED); |
| 1142 set_require_confirmation(true); | 1148 set_require_confirmation(true); |
| 1143 } | 1149 } |
| 1144 | 1150 |
| 1151 void QuicStreamFactory::OnNetworkConnected(NetworkHandle network) { | |
| 1152 // Nothing to do. | |
| 1153 } | |
| 1154 | |
| 1155 void QuicStreamFactory::OnNetworkMadeDefault(NetworkHandle network) { | |
| 1156 // Nothing to do. | |
| 1157 } | |
| 1158 | |
| 1159 void QuicStreamFactory::OnNetworkDisconnected(NetworkHandle network) { | |
| 1160 MigrateOrCloseSessions(network); | |
| 1161 } | |
| 1162 | |
| 1163 void QuicStreamFactory::OnNetworkSoonToDisconnect(NetworkHandle network) { | |
| 1164 MigrateOrCloseSessions(network); | |
| 1165 } | |
| 1166 | |
| 1167 void QuicStreamFactory::MigrateOrCloseSessions(NetworkHandle network) { | |
| 1168 // 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.
| |
| 1169 NetworkList network_list; | |
| 1170 GetConnectedNetworks(&network_list); | |
| 1171 if (network_list.isEmpty() || | |
| 1172 (network_list.size() == 1 && network_list[0] == network)) { | |
| 1173 CloseAllSessions(ERR_NETWORK_CHANGED); | |
| 1174 set_require_confirmation(true); | |
| 1175 return; | |
| 1176 } | |
| 1177 | |
| 1178 // Find a new network that old sockets can be migrated to. | |
| 1179 // 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.
| |
| 1180 NetworkHandle new_network = kInvalidNetworkHandle; | |
| 1181 for (NetworkHandle n : network_list) { | |
| 1182 if (n == network) { | |
| 1183 continue; | |
| 1184 } | |
| 1185 new_network = n; | |
| 1186 } | |
| 1187 | |
| 1188 DCHECK_NE(kInvalidNetworkHandle, new_network); | |
| 1189 DCHECK_NE(network, new_network); | |
| 1190 | |
| 1191 for (QuicStreamFactory::SessionIdMap::iterator it = all_sessions_.begin(); | |
| 1192 it != all_sessions_.end(); ++it) { | |
| 1193 QuicChromiumClientSession* session = it->first; | |
| 1194 QuicServerId server_id = it->second; | |
| 1195 | |
| 1196 if (session->GetNumOpenStreams() == 0) { | |
| 1197 // If idle session, close session | |
| 1198 active_sessions_.erase(server_id); | |
| 1199 session->CloseSessionOnError(ERR_NETWORK_CHANGED, QUIC_INTERNAL_ERROR); | |
| 1200 } else if (session->current_network() == new_network) { | |
| 1201 // @@@ TODO (jri): store network and record in session when | |
| 1202 // BindToNetwork() is called. | |
| 1203 // If session is already using |network|, move on. | |
| 1204 continue; | |
| 1205 } else { | |
| 1206 // If session is active, | |
| 1207 // (i) make the session GO_AWAY, | |
| 1208 // (ii) create a new socket (which should be bound to the new interface), | |
| 1209 // (iii) add a new PacketReader to the session to read from new socket, | |
| 1210 // (iv) replace the connection's PacketWriter with a new PacketWriter | |
| 1211 // that uses the new socket. | |
| 1212 set_require_confirmation(true); | |
| 1213 OnSessionGoingAway(session); | |
| 1214 scoped_ptr<DatagramClientSocket> socket; | |
| 1215 int rv = CreateAndConfigureDatagramSocket(&socket, | |
| 1216 all_sessions[*session], | |
| 1217 connection->peer_address(), | |
| 1218 session->net_log(), | |
| 1219 new_network); | |
| 1220 if (rv != OK) { | |
| 1221 session->CloseSessionOnError(ERR_NETWORK_CHANGED, QUIC_INTERNAL_ERROR); | |
| 1222 continue; | |
| 1223 } | |
| 1224 | |
| 1225 if (!session->AddPacketReader(new QuicPacketReader(socket.get(), | |
| 1226 clock_.get(), | |
| 1227 session, | |
| 1228 yield_after_packets_, | |
| 1229 yield_after_duration_, | |
| 1230 session->net_log()))) { | |
| 1231 session->CloseSessionOnError(ERR_NETWORK_CHANGED, QUIC_INTERNAL_ERROR); | |
| 1232 continue; | |
| 1233 } | |
| 1234 | |
| 1235 session->StartReading(); | |
| 1236 DefaultPacketWriterFactory packet_writer_factory(socket.get()); | |
| 1237 QuicConnection* connection = session->connection(); | |
| 1238 connection->SetQuicPacketWriter(packet_writer_factory.Create(connection), | |
| 1239 /*owns_writer=*/true); | |
| 1240 | |
| 1241 session->AddSocket(socket.Pass()); | |
| 1242 } | |
| 1243 } | |
| 1244 } | |
| 1245 | |
| 1145 void QuicStreamFactory::OnSSLConfigChanged() { | 1246 void QuicStreamFactory::OnSSLConfigChanged() { |
| 1146 CloseAllSessions(ERR_CERT_DATABASE_CHANGED); | 1247 CloseAllSessions(ERR_CERT_DATABASE_CHANGED); |
| 1147 } | 1248 } |
| 1148 | 1249 |
| 1149 void QuicStreamFactory::OnCertAdded(const X509Certificate* cert) { | 1250 void QuicStreamFactory::OnCertAdded(const X509Certificate* cert) { |
| 1150 CloseAllSessions(ERR_CERT_DATABASE_CHANGED); | 1251 CloseAllSessions(ERR_CERT_DATABASE_CHANGED); |
| 1151 } | 1252 } |
| 1152 | 1253 |
| 1153 void QuicStreamFactory::OnCACertChanged(const X509Certificate* cert) { | 1254 void QuicStreamFactory::OnCACertChanged(const X509Certificate* cert) { |
| 1154 // We should flush the sessions if we removed trust from a | 1255 // We should flush the sessions if we removed trust from a |
| (...skipping 10 matching lines...) Expand all Loading... | |
| 1165 | 1266 |
| 1166 bool QuicStreamFactory::HasActiveSession( | 1267 bool QuicStreamFactory::HasActiveSession( |
| 1167 const QuicServerId& server_id) const { | 1268 const QuicServerId& server_id) const { |
| 1168 return ContainsKey(active_sessions_, server_id); | 1269 return ContainsKey(active_sessions_, server_id); |
| 1169 } | 1270 } |
| 1170 | 1271 |
| 1171 bool QuicStreamFactory::HasActiveJob(const QuicServerId& key) const { | 1272 bool QuicStreamFactory::HasActiveJob(const QuicServerId& key) const { |
| 1172 return ContainsKey(active_jobs_, key); | 1273 return ContainsKey(active_jobs_, key); |
| 1173 } | 1274 } |
| 1174 | 1275 |
| 1175 int QuicStreamFactory::CreateSession(const QuicServerId& server_id, | 1276 int QuicStreamFactory::CreateAndConfigureDatagramSocket( |
| 1176 int cert_verify_flags, | 1277 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.
| |
| 1177 scoped_ptr<QuicServerInfo> server_info, | 1278 const QuicServerId& server_id, |
| 1178 const AddressList& address_list, | 1279 IPEndPoint addr, |
| 1179 base::TimeTicks dns_resolution_end_time, | 1280 const BoundNetLog& net_log, |
| 1180 const BoundNetLog& net_log, | 1281 NetworkHandle network) { |
| 1181 QuicChromiumClientSession** session) { | |
| 1182 bool enable_port_selection = enable_port_selection_; | 1282 bool enable_port_selection = enable_port_selection_; |
| 1183 if (enable_port_selection && | 1283 if (enable_port_selection && |
| 1184 ContainsKey(gone_away_aliases_, server_id)) { | 1284 ContainsKey(gone_away_aliases_, server_id)) { |
| 1185 // Disable port selection when the server is going away. | 1285 // Disable port selection when the server is going away. |
| 1186 // There is no point in trying to return to the same server, if | 1286 // There is no point in trying to return to the same server, if |
| 1187 // that server is no longer handling requests. | 1287 // that server is no longer handling requests. |
| 1188 enable_port_selection = false; | 1288 enable_port_selection = false; |
| 1189 gone_away_aliases_.erase(server_id); | 1289 gone_away_aliases_.erase(server_id); |
| 1190 } | 1290 } |
| 1191 | 1291 |
| 1192 QuicConnectionId connection_id = random_generator_->RandUint64(); | |
| 1193 IPEndPoint addr = *address_list.begin(); | |
| 1194 scoped_refptr<PortSuggester> port_suggester = | 1292 scoped_refptr<PortSuggester> port_suggester = |
| 1195 new PortSuggester(server_id.host_port_pair(), port_seed_); | 1293 new PortSuggester(server_id.host_port_pair(), port_seed_); |
| 1196 DatagramSocket::BindType bind_type = enable_port_selection ? | 1294 DatagramSocket::BindType bind_type = enable_port_selection ? |
| 1197 DatagramSocket::RANDOM_BIND : // Use our callback. | 1295 DatagramSocket::RANDOM_BIND : // Use our callback. |
| 1198 DatagramSocket::DEFAULT_BIND; // Use OS to randomize. | 1296 DatagramSocket::DEFAULT_BIND; // Use OS to randomize. |
| 1199 scoped_ptr<DatagramClientSocket> socket( | 1297 scoped_ptr<DatagramClientSocket> socket( |
| 1200 client_socket_factory_->CreateDatagramClientSocket( | 1298 client_socket_factory_->CreateDatagramClientSocket( |
| 1201 bind_type, | 1299 bind_type, |
| 1202 base::Bind(&PortSuggester::SuggestPort, port_suggester), | 1300 base::Bind(&PortSuggester::SuggestPort, port_suggester), |
| 1203 net_log.net_log(), net_log.source())); | 1301 net_log.net_log(), net_log.source())); |
| 1204 | 1302 |
| 1205 if (enable_non_blocking_io_ && | 1303 if (enable_non_blocking_io_ && |
| 1206 client_socket_factory_ == ClientSocketFactory::GetDefaultFactory()) { | 1304 client_socket_factory_ == ClientSocketFactory::GetDefaultFactory()) { |
| 1207 #if defined(OS_WIN) | 1305 #if defined(OS_WIN) |
| 1208 static_cast<UDPClientSocket*>(socket.get())->UseNonBlockingIO(); | 1306 static_cast<UDPClientSocket*>(socket.get())->UseNonBlockingIO(); |
| 1209 #endif | 1307 #endif |
| 1210 } | 1308 } |
| 1211 | 1309 |
| 1212 int rv = socket->Connect(addr); | 1310 // If caller leaves network unspecified, find current default. |
| 1311 if (network == kDefaultNetworkHandle) { | |
| 1312 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
| |
| 1313 if (network == kDefaultNetworkHandle) { | |
| 1314 return ERR_INTERNET_DISCONNECTED; | |
| 1315 } | |
| 1316 } | |
| 1213 | 1317 |
| 1318 new_socket->Reset(socket.get()); | |
| 1319 | |
| 1320 int rv = socket->BindToNetwork(network); | |
| 1321 if (rv != OK) { | |
| 1322 return rv; | |
| 1323 } | |
| 1324 | |
| 1325 rv = socket->Connect(addr); | |
| 1214 if (rv != OK) { | 1326 if (rv != OK) { |
| 1215 HistogramCreateSessionFailure(CREATION_ERROR_CONNECTING_SOCKET); | 1327 HistogramCreateSessionFailure(CREATION_ERROR_CONNECTING_SOCKET); |
| 1216 return rv; | 1328 return rv; |
| 1217 } | 1329 } |
| 1218 UMA_HISTOGRAM_COUNTS("Net.QuicEphemeralPortsSuggested", | 1330 UMA_HISTOGRAM_COUNTS("Net.QuicEphemeralPortsSuggested", |
| 1219 port_suggester->call_count()); | 1331 port_suggester->call_count()); |
| 1220 if (enable_port_selection) { | 1332 if (enable_port_selection) { |
| 1221 DCHECK_LE(1u, port_suggester->call_count()); | 1333 DCHECK_LE(1u, port_suggester->call_count()); |
| 1222 } else { | 1334 } else { |
| 1223 DCHECK_EQ(0u, port_suggester->call_count()); | 1335 DCHECK_EQ(0u, port_suggester->call_count()); |
| (...skipping 15 matching lines...) Expand all Loading... | |
| 1239 | 1351 |
| 1240 socket->GetLocalAddress(&local_address_); | 1352 socket->GetLocalAddress(&local_address_); |
| 1241 if (check_persisted_supports_quic_ && http_server_properties_) { | 1353 if (check_persisted_supports_quic_ && http_server_properties_) { |
| 1242 check_persisted_supports_quic_ = false; | 1354 check_persisted_supports_quic_ = false; |
| 1243 IPAddressNumber last_address; | 1355 IPAddressNumber last_address; |
| 1244 if (http_server_properties_->GetSupportsQuic(&last_address) && | 1356 if (http_server_properties_->GetSupportsQuic(&last_address) && |
| 1245 last_address == local_address_.address()) { | 1357 last_address == local_address_.address()) { |
| 1246 require_confirmation_ = false; | 1358 require_confirmation_ = false; |
| 1247 } | 1359 } |
| 1248 } | 1360 } |
| 1361 return OK; | |
| 1362 } | |
| 1363 | |
| 1364 int QuicStreamFactory::CreateSession(const QuicServerId& server_id, | |
| 1365 int cert_verify_flags, | |
| 1366 scoped_ptr<QuicServerInfo> server_info, | |
| 1367 const AddressList& address_list, | |
| 1368 base::TimeTicks dns_resolution_end_time, | |
| 1369 const BoundNetLog& net_log, | |
| 1370 QuicChromiumClientSession** session) { | |
| 1371 scoped_ptr<DatagramClientSocket> socket; | |
| 1372 int rv = CreateAndConfigureDatagramSocket(&socket, | |
| 1373 server_id, | |
| 1374 *address_list.begin(), | |
| 1375 net_log, | |
| 1376 kDefaultNetworkHandle); | |
| 1377 if (rv != OK) { | |
| 1378 return rv; | |
| 1379 } | |
| 1249 | 1380 |
| 1250 DefaultPacketWriterFactory packet_writer_factory(socket.get()); | 1381 DefaultPacketWriterFactory packet_writer_factory(socket.get()); |
| 1251 | |
| 1252 if (!helper_.get()) { | 1382 if (!helper_.get()) { |
| 1253 helper_.reset( | 1383 helper_.reset( |
| 1254 new QuicConnectionHelper(base::ThreadTaskRunnerHandle::Get().get(), | 1384 new QuicConnectionHelper(base::ThreadTaskRunnerHandle::Get().get(), |
| 1255 clock_.get(), random_generator_)); | 1385 clock_.get(), random_generator_)); |
| 1256 } | 1386 } |
| 1257 | 1387 |
| 1388 QuicConnectionId connection_id = random_generator_->RandUint64(); | |
| 1258 QuicConnection* connection = new QuicConnection( | 1389 QuicConnection* connection = new QuicConnection( |
| 1259 connection_id, addr, helper_.get(), packet_writer_factory, | 1390 connection_id, addr, helper_.get(), packet_writer_factory, |
| 1260 true /* owns_writer */, Perspective::IS_CLIENT, server_id.is_https(), | 1391 true /* owns_writer */, Perspective::IS_CLIENT, server_id.is_https(), |
| 1261 supported_versions_); | 1392 supported_versions_); |
| 1262 connection->SetMaxPacketLength(max_packet_length_); | 1393 connection->SetMaxPacketLength(max_packet_length_); |
| 1263 | 1394 |
| 1264 InitializeCachedStateInCryptoConfig(server_id, server_info); | 1395 InitializeCachedStateInCryptoConfig(server_id, server_info); |
| 1265 | 1396 |
| 1266 QuicConfig config = config_; | 1397 QuicConfig config = config_; |
| 1267 config.SetSocketReceiveBufferToSend(socket_receive_buffer_size_); | 1398 config.SetSocketReceiveBufferToSend(socket_receive_buffer_size_); |
| (...skipping 178 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1446 // Since the session was active, there's no longer an | 1577 // Since the session was active, there's no longer an |
| 1447 // HttpStreamFactoryImpl::Job running which can mark it broken, unless the TCP | 1578 // HttpStreamFactoryImpl::Job running which can mark it broken, unless the TCP |
| 1448 // job also fails. So to avoid not using QUIC when we otherwise could, we mark | 1579 // job also fails. So to avoid not using QUIC when we otherwise could, we mark |
| 1449 // it as recently broken, which means that 0-RTT will be disabled but we'll | 1580 // it as recently broken, which means that 0-RTT will be disabled but we'll |
| 1450 // still race. | 1581 // still race. |
| 1451 http_server_properties_->MarkAlternativeServiceRecentlyBroken( | 1582 http_server_properties_->MarkAlternativeServiceRecentlyBroken( |
| 1452 alternative_service); | 1583 alternative_service); |
| 1453 } | 1584 } |
| 1454 | 1585 |
| 1455 } // namespace net | 1586 } // namespace net |
| OLD | NEW |