OLD | NEW |
---|---|
1 /* | 1 /* |
2 * Copyright 2004 The WebRTC Project Authors. All rights reserved. | 2 * Copyright 2004 The WebRTC Project Authors. All rights reserved. |
3 * | 3 * |
4 * Use of this source code is governed by a BSD-style license | 4 * Use of this source code is governed by a BSD-style license |
5 * that can be found in the LICENSE file in the root of the source | 5 * that can be found in the LICENSE file in the root of the source |
6 * tree. An additional intellectual property rights grant can be found | 6 * tree. An additional intellectual property rights grant can be found |
7 * in the file PATENTS. All contributing project authors may | 7 * in the file PATENTS. All contributing project authors may |
8 * be found in the AUTHORS file in the root of the source tree. | 8 * be found in the AUTHORS file in the root of the source tree. |
9 */ | 9 */ |
10 | 10 |
11 #include "webrtc/p2p/base/p2ptransportchannel.h" | 11 #include "webrtc/p2p/base/p2ptransportchannel.h" |
12 | 12 |
13 #include <algorithm> | 13 #include <algorithm> |
14 #include <set> | 14 #include <set> |
15 | 15 |
16 #include "webrtc/base/common.h" | 16 #include "webrtc/base/common.h" |
17 #include "webrtc/base/crc32.h" | 17 #include "webrtc/base/crc32.h" |
18 #include "webrtc/base/logging.h" | 18 #include "webrtc/base/logging.h" |
19 #include "webrtc/base/stringencode.h" | 19 #include "webrtc/base/stringencode.h" |
20 #include "webrtc/p2p/base/candidate.h" | 20 #include "webrtc/p2p/base/candidate.h" |
21 #include "webrtc/p2p/base/candidatepairinterface.h" | 21 #include "webrtc/p2p/base/candidatepairinterface.h" |
22 #include "webrtc/p2p/base/common.h" | 22 #include "webrtc/p2p/base/common.h" |
23 #include "webrtc/p2p/base/relayport.h" // For RELAY_PORT_TYPE. | 23 #include "webrtc/p2p/base/relayport.h" // For RELAY_PORT_TYPE. |
24 #include "webrtc/p2p/base/stunport.h" // For STUN_PORT_TYPE. | 24 #include "webrtc/p2p/base/stunport.h" // For STUN_PORT_TYPE. |
25 #include "webrtc/system_wrappers/include/field_trial.h" | 25 #include "webrtc/system_wrappers/include/field_trial.h" |
26 | 26 |
27 namespace { | 27 namespace { |
28 | 28 |
29 // messages for queuing up work for ourselves | 29 // messages for queuing up work for ourselves |
30 enum { MSG_SORT = 1, MSG_CHECK_AND_PING }; | 30 enum { |
31 MSG_SORT = 1, | |
32 MSG_CHECK_AND_PING, | |
33 MSG_CHECK_RESTORE_BACKUP_CONNECTION, | |
34 MSG_SIGNAL_CANDIDATES_REMOVED | |
35 }; | |
31 | 36 |
32 // The minimum improvement in RTT that justifies a switch. | 37 // The minimum improvement in RTT that justifies a switch. |
33 static const double kMinImprovement = 10; | 38 const double kMinImprovement = 10; |
34 | 39 |
35 bool IsRelayRelay(cricket::Connection* conn) { | 40 bool IsRelayRelay(cricket::Connection* conn) { |
36 return conn->local_candidate().type() == cricket::RELAY_PORT_TYPE && | 41 return conn->local_candidate().type() == cricket::RELAY_PORT_TYPE && |
37 conn->remote_candidate().type() == cricket::RELAY_PORT_TYPE; | 42 conn->remote_candidate().type() == cricket::RELAY_PORT_TYPE; |
38 } | 43 } |
39 | 44 |
40 bool IsUdp(cricket::Connection* conn) { | 45 bool IsUdp(cricket::Connection* conn) { |
41 return conn->local_candidate().relay_protocol() == cricket::UDP_PROTOCOL_NAME; | 46 return conn->local_candidate().relay_protocol() == cricket::UDP_PROTOCOL_NAME; |
42 } | 47 } |
43 | 48 |
(...skipping 173 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
217 // writable or not receiving. | 222 // writable or not receiving. |
218 const int WEAK_PING_INTERVAL = 1000 * PING_PACKET_SIZE / 10000; | 223 const int WEAK_PING_INTERVAL = 1000 * PING_PACKET_SIZE / 10000; |
219 | 224 |
220 // If the current best connection is both writable and receiving, then we will | 225 // If the current best connection is both writable and receiving, then we will |
221 // also try hard to make sure it is pinged at this rate (a little less than | 226 // also try hard to make sure it is pinged at this rate (a little less than |
222 // 2 * STRONG_PING_INTERVAL). | 227 // 2 * STRONG_PING_INTERVAL). |
223 static const int MAX_CURRENT_STRONG_INTERVAL = 900; // ms | 228 static const int MAX_CURRENT_STRONG_INTERVAL = 900; // ms |
224 | 229 |
225 static const int MIN_CHECK_RECEIVING_INTERVAL = 50; // ms | 230 static const int MIN_CHECK_RECEIVING_INTERVAL = 50; // ms |
226 | 231 |
232 // We periodically check and restore backup connections on existing networks | |
233 // that do not have any connection at this interval. | |
234 static const int CHECK_RESTORE_BACKUP_CONNECTION_INTERVAL = 5 * 60 * 1000; | |
235 | |
227 P2PTransportChannel::P2PTransportChannel(const std::string& transport_name, | 236 P2PTransportChannel::P2PTransportChannel(const std::string& transport_name, |
228 int component, | 237 int component, |
229 P2PTransport* transport, | 238 P2PTransport* transport, |
230 PortAllocator* allocator) | 239 PortAllocator* allocator) |
231 : P2PTransportChannel(transport_name, component, allocator) {} | 240 : P2PTransportChannel(transport_name, component, allocator) {} |
232 | 241 |
233 P2PTransportChannel::P2PTransportChannel(const std::string& transport_name, | 242 P2PTransportChannel::P2PTransportChannel(const std::string& transport_name, |
234 int component, | 243 int component, |
235 PortAllocator* allocator) | 244 PortAllocator* allocator) |
236 : TransportChannelImpl(transport_name, component), | 245 : TransportChannelImpl(transport_name, component), |
237 allocator_(allocator), | 246 allocator_(allocator), |
238 worker_thread_(rtc::Thread::Current()), | 247 worker_thread_(rtc::Thread::Current()), |
239 incoming_only_(false), | 248 incoming_only_(false), |
240 error_(0), | 249 error_(0), |
241 best_connection_(NULL), | 250 best_connection_(NULL), |
242 pending_best_connection_(NULL), | 251 pending_best_connection_(NULL), |
243 sort_dirty_(false), | 252 sort_dirty_(false), |
244 remote_ice_mode_(ICEMODE_FULL), | 253 remote_ice_mode_(ICEMODE_FULL), |
245 ice_role_(ICEROLE_UNKNOWN), | 254 ice_role_(ICEROLE_UNKNOWN), |
246 tiebreaker_(0), | 255 tiebreaker_(0), |
247 gathering_state_(kIceGatheringNew), | 256 gathering_state_(kIceGatheringNew), |
248 check_receiving_interval_(MIN_CHECK_RECEIVING_INTERVAL * 5), | 257 check_receiving_interval_(MIN_CHECK_RECEIVING_INTERVAL * 5), |
258 check_restore_backup_connection_interval_( | |
259 CHECK_RESTORE_BACKUP_CONNECTION_INTERVAL), | |
249 config_(MIN_CHECK_RECEIVING_INTERVAL * 50 /* receiving_timeout */, | 260 config_(MIN_CHECK_RECEIVING_INTERVAL * 50 /* receiving_timeout */, |
250 0 /* backup_connection_ping_interval */, | 261 0 /* backup_connection_ping_interval */, |
251 false /* gather_continually */, | 262 false /* gather_continually */, |
252 false /* prioritize_most_likely_candidate_pairs */, | 263 false /* prioritize_most_likely_candidate_pairs */, |
253 MAX_CURRENT_STRONG_INTERVAL /* max_strong_interval */) { | 264 MAX_CURRENT_STRONG_INTERVAL /* max_strong_interval */) { |
254 uint32_t weak_ping_interval = ::strtoul( | 265 uint32_t weak_ping_interval = ::strtoul( |
255 webrtc::field_trial::FindFullName("WebRTC-StunInterPacketDelay").c_str(), | 266 webrtc::field_trial::FindFullName("WebRTC-StunInterPacketDelay").c_str(), |
256 nullptr, 10); | 267 nullptr, 10); |
257 if (weak_ping_interval) { | 268 if (weak_ping_interval) { |
258 weak_ping_interval_ = static_cast<int>(weak_ping_interval); | 269 weak_ping_interval_ = static_cast<int>(weak_ping_interval); |
(...skipping 14 matching lines...) Expand all Loading... | |
273 session->SignalPortReady.connect(this, &P2PTransportChannel::OnPortReady); | 284 session->SignalPortReady.connect(this, &P2PTransportChannel::OnPortReady); |
274 session->SignalCandidatesReady.connect( | 285 session->SignalCandidatesReady.connect( |
275 this, &P2PTransportChannel::OnCandidatesReady); | 286 this, &P2PTransportChannel::OnCandidatesReady); |
276 session->SignalCandidatesAllocationDone.connect( | 287 session->SignalCandidatesAllocationDone.connect( |
277 this, &P2PTransportChannel::OnCandidatesAllocationDone); | 288 this, &P2PTransportChannel::OnCandidatesAllocationDone); |
278 | 289 |
279 // We now only want to apply new candidates that we receive to the ports | 290 // We now only want to apply new candidates that we receive to the ports |
280 // created by this new session because these are replacing those of the | 291 // created by this new session because these are replacing those of the |
281 // previous sessions. | 292 // previous sessions. |
282 ports_.clear(); | 293 ports_.clear(); |
294 // We do not need to signal the candidate removals because a new allocator | |
295 // session indicates an ICE restart, which will remove all old remote | |
296 // candidates on the other side. | |
297 candidates_removed_.clear(); | |
283 | 298 |
284 allocator_sessions_.push_back(std::move(session)); | 299 allocator_sessions_.push_back(std::move(session)); |
285 } | 300 } |
286 | 301 |
287 void P2PTransportChannel::AddConnection(Connection* connection) { | 302 void P2PTransportChannel::AddConnection(Connection* connection) { |
288 connections_.push_back(connection); | 303 connections_.push_back(connection); |
289 unpinged_connections_.insert(connection); | 304 unpinged_connections_.insert(connection); |
290 connection->set_remote_ice_mode(remote_ice_mode_); | 305 connection->set_remote_ice_mode(remote_ice_mode_); |
291 connection->set_receiving_timeout(config_.receiving_timeout); | 306 connection->set_receiving_timeout(config_.receiving_timeout); |
292 connection->SignalReadPacket.connect( | 307 connection->SignalReadPacket.connect( |
(...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
333 if (!had_connection_) { | 348 if (!had_connection_) { |
334 return TransportChannelState::STATE_INIT; | 349 return TransportChannelState::STATE_INIT; |
335 } | 350 } |
336 | 351 |
337 std::vector<Connection*> active_connections; | 352 std::vector<Connection*> active_connections; |
338 for (Connection* connection : connections_) { | 353 for (Connection* connection : connections_) { |
339 if (connection->active()) { | 354 if (connection->active()) { |
340 active_connections.push_back(connection); | 355 active_connections.push_back(connection); |
341 } | 356 } |
342 } | 357 } |
343 if (active_connections.empty()) { | 358 // TODO(honghaiz): We should expose one transport channel state to the |
359 // the external world (e.g. TransportController), so that we won't need to | |
360 // make both writable and channel state depend on IsRecoveringConnectivity. | |
361 if (active_connections.empty() && !IsRecoveringConnectivity()) { | |
344 return TransportChannelState::STATE_FAILED; | 362 return TransportChannelState::STATE_FAILED; |
345 } | 363 } |
346 | 364 |
347 std::set<rtc::Network*> networks; | 365 std::set<rtc::Network*> networks; |
348 for (Connection* connection : active_connections) { | 366 for (Connection* connection : active_connections) { |
349 rtc::Network* network = connection->port()->Network(); | 367 rtc::Network* network = connection->port()->Network(); |
350 if (networks.find(network) == networks.end()) { | 368 if (networks.find(network) == networks.end()) { |
351 networks.insert(network); | 369 networks.insert(network); |
352 } else { | 370 } else { |
353 LOG_J(LS_VERBOSE, this) << "Ice not completed yet for this channel as " | 371 LOG_J(LS_VERBOSE, this) << "Ice not completed yet for this channel as " |
(...skipping 95 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
449 ASSERT(worker_thread_ == rtc::Thread::Current()); | 467 ASSERT(worker_thread_ == rtc::Thread::Current()); |
450 if (ice_ufrag_.empty() || ice_pwd_.empty()) { | 468 if (ice_ufrag_.empty() || ice_pwd_.empty()) { |
451 ASSERT(false); | 469 ASSERT(false); |
452 LOG(LS_ERROR) << "P2PTransportChannel::Connect: The ice_ufrag_ and the " | 470 LOG(LS_ERROR) << "P2PTransportChannel::Connect: The ice_ufrag_ and the " |
453 << "ice_pwd_ are not set."; | 471 << "ice_pwd_ are not set."; |
454 return; | 472 return; |
455 } | 473 } |
456 | 474 |
457 // Start checking and pinging as the ports come in. | 475 // Start checking and pinging as the ports come in. |
458 thread()->Post(this, MSG_CHECK_AND_PING); | 476 thread()->Post(this, MSG_CHECK_AND_PING); |
477 thread()->PostDelayed(check_restore_backup_connection_interval_, this, | |
478 MSG_CHECK_RESTORE_BACKUP_CONNECTION); | |
459 } | 479 } |
460 | 480 |
461 void P2PTransportChannel::MaybeStartGathering() { | 481 void P2PTransportChannel::MaybeStartGathering() { |
462 // Start gathering if we never started before, or if an ICE restart occurred. | 482 // Start gathering if we never started before, or if an ICE restart occurred. |
463 if (allocator_sessions_.empty() || | 483 if (allocator_sessions_.empty() || |
464 IceCredentialsChanged(allocator_sessions_.back()->ice_ufrag(), | 484 IceCredentialsChanged(allocator_sessions_.back()->ice_ufrag(), |
465 allocator_sessions_.back()->ice_pwd(), ice_ufrag_, | 485 allocator_sessions_.back()->ice_pwd(), ice_ufrag_, |
466 ice_pwd_)) { | 486 ice_pwd_)) { |
467 if (gathering_state_ != kIceGatheringGathering) { | 487 if (gathering_state_ != kIceGatheringGathering) { |
468 gathering_state_ = kIceGatheringGathering; | 488 gathering_state_ = kIceGatheringGathering; |
(...skipping 761 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1230 RTC_DCHECK(state == STATE_CONNECTING || state == STATE_COMPLETED); | 1250 RTC_DCHECK(state == STATE_CONNECTING || state == STATE_COMPLETED); |
1231 break; | 1251 break; |
1232 default: | 1252 default: |
1233 RTC_DCHECK(false); | 1253 RTC_DCHECK(false); |
1234 break; | 1254 break; |
1235 } | 1255 } |
1236 state_ = state; | 1256 state_ = state; |
1237 SignalStateChanged(this); | 1257 SignalStateChanged(this); |
1238 } | 1258 } |
1239 | 1259 |
1240 bool writable = best_connection_ && best_connection_->writable(); | 1260 // If it is recovering connectivity, it is considered writable to the |
1261 // external world. | |
Taylor Brandstetter
2016/06/06 18:18:37
When you say "external world", do you mean applica
honghaiz3
2016/06/07 16:42:06
I meant the TransportController and the layers abo
Taylor Brandstetter
2016/06/07 17:13:26
If the application is using continual gathering, i
| |
1262 bool writable = (best_connection_ && best_connection_->writable()) || | |
1263 IsRecoveringConnectivity(); | |
1241 set_writable(writable); | 1264 set_writable(writable); |
1242 | 1265 |
1243 bool receiving = false; | 1266 bool receiving = false; |
1244 for (const Connection* connection : connections_) { | 1267 for (const Connection* connection : connections_) { |
1245 if (connection->receiving()) { | 1268 if (connection->receiving()) { |
1246 receiving = true; | 1269 receiving = true; |
1247 break; | 1270 break; |
1248 } | 1271 } |
1249 } | 1272 } |
1250 set_receiving(receiving); | 1273 set_receiving(receiving); |
(...skipping 48 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1299 | 1322 |
1300 // Handle any queued up requests | 1323 // Handle any queued up requests |
1301 void P2PTransportChannel::OnMessage(rtc::Message *pmsg) { | 1324 void P2PTransportChannel::OnMessage(rtc::Message *pmsg) { |
1302 switch (pmsg->message_id) { | 1325 switch (pmsg->message_id) { |
1303 case MSG_SORT: | 1326 case MSG_SORT: |
1304 OnSort(); | 1327 OnSort(); |
1305 break; | 1328 break; |
1306 case MSG_CHECK_AND_PING: | 1329 case MSG_CHECK_AND_PING: |
1307 OnCheckAndPing(); | 1330 OnCheckAndPing(); |
1308 break; | 1331 break; |
1332 case MSG_CHECK_RESTORE_BACKUP_CONNECTION: | |
1333 OnCheckAndRestoreBackupConnection(); | |
1334 break; | |
1335 case MSG_SIGNAL_CANDIDATES_REMOVED: | |
1336 if (!candidates_removed_.empty()) { | |
1337 LOG(LS_INFO) << "Signal removing " << candidates_removed_.size() | |
1338 << " candidates"; | |
1339 SignalCandidatesRemoved(this, candidates_removed_); | |
1340 candidates_removed_.clear(); | |
1341 } | |
1342 break; | |
1309 default: | 1343 default: |
1310 ASSERT(false); | 1344 ASSERT(false); |
1311 break; | 1345 break; |
1312 } | 1346 } |
1313 } | 1347 } |
1314 | 1348 |
1315 // Handle queued up sort request | 1349 // Handle queued up sort request |
1316 void P2PTransportChannel::OnSort() { | 1350 void P2PTransportChannel::OnSort() { |
1317 // Resort the connections based on the new statistics. | 1351 // Resort the connections based on the new statistics. |
1318 SortConnections(); | 1352 SortConnections(); |
(...skipping 18 matching lines...) Expand all Loading... | |
1337 Connection* conn = FindNextPingableConnection(); | 1371 Connection* conn = FindNextPingableConnection(); |
1338 if (conn) { | 1372 if (conn) { |
1339 PingConnection(conn); | 1373 PingConnection(conn); |
1340 MarkConnectionPinged(conn); | 1374 MarkConnectionPinged(conn); |
1341 } | 1375 } |
1342 } | 1376 } |
1343 int delay = std::min(ping_interval, check_receiving_interval_); | 1377 int delay = std::min(ping_interval, check_receiving_interval_); |
1344 thread()->PostDelayed(delay, this, MSG_CHECK_AND_PING); | 1378 thread()->PostDelayed(delay, this, MSG_CHECK_AND_PING); |
1345 } | 1379 } |
1346 | 1380 |
1381 void P2PTransportChannel::OnCheckAndRestoreBackupConnection() { | |
1382 if (!config_.gather_continually) { | |
1383 return; | |
1384 } | |
1385 rtc::NetworkManager::NetworkList networks; | |
1386 allocator_->GetNetworks(&networks); | |
1387 // Filter out loopback networks. | |
1388 auto network_end = std::remove_if( | |
1389 networks.begin(), networks.end(), [](rtc::Network* network) { | |
1390 return network->type() == rtc::ADAPTER_TYPE_LOOPBACK; | |
1391 }); | |
1392 | |
1393 // Filter out networks having connections in non-failed state. | |
1394 for (Connection* conn : connections_) { | |
1395 if (conn->state() == Connection::STATE_FAILED) { | |
1396 continue; | |
1397 } | |
1398 const std::string& interface_name = conn->port()->Network()->name(); | |
1399 network_end = std::remove_if(networks.begin(), network_end, | |
1400 [interface_name](rtc::Network* net) { | |
1401 return net->name() == interface_name; | |
1402 }); | |
1403 if (networks.begin() == network_end) { | |
1404 break; | |
1405 } | |
1406 } | |
1407 networks.erase(network_end, networks.end()); | |
1408 if (!networks.empty()) { | |
1409 StartRegathering(&networks); | |
1410 } | |
1411 | |
1412 thread()->PostDelayed(check_restore_backup_connection_interval_, this, | |
1413 MSG_CHECK_RESTORE_BACKUP_CONNECTION); | |
1414 } | |
1415 | |
1347 // A connection is considered a backup connection if the channel state | 1416 // A connection is considered a backup connection if the channel state |
1348 // is completed, the connection is not the best connection and it is active. | 1417 // is completed, the connection is not the best connection and it is active. |
1349 bool P2PTransportChannel::IsBackupConnection(Connection* conn) const { | 1418 bool P2PTransportChannel::IsBackupConnection(Connection* conn) const { |
1350 return state_ == STATE_COMPLETED && conn != best_connection_ && | 1419 return state_ == STATE_COMPLETED && conn != best_connection_ && |
1351 conn->active(); | 1420 conn->active(); |
1352 } | 1421 } |
1353 | 1422 |
1354 // Is the connection in a state for us to even consider pinging the other side? | 1423 // Is the connection in a state for us to even consider pinging the other side? |
1355 // We consider a connection pingable even if it's not connected because that's | 1424 // We consider a connection pingable even if it's not connected because that's |
1356 // how a TCP connection is kicked into reconnecting on the active side. | 1425 // how a TCP connection is kicked into reconnecting on the active side. |
(...skipping 47 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1404 } | 1473 } |
1405 return conn_to_ping; | 1474 return conn_to_ping; |
1406 } | 1475 } |
1407 | 1476 |
1408 void P2PTransportChannel::MarkConnectionPinged(Connection* conn) { | 1477 void P2PTransportChannel::MarkConnectionPinged(Connection* conn) { |
1409 if (conn && pinged_connections_.insert(conn).second) { | 1478 if (conn && pinged_connections_.insert(conn).second) { |
1410 unpinged_connections_.erase(conn); | 1479 unpinged_connections_.erase(conn); |
1411 } | 1480 } |
1412 } | 1481 } |
1413 | 1482 |
1483 void P2PTransportChannel::set_check_restore_backup_connection_interval( | |
1484 int interval) { | |
1485 check_restore_backup_connection_interval_ = interval; | |
1486 thread()->Clear(this, MSG_CHECK_RESTORE_BACKUP_CONNECTION, nullptr); | |
1487 thread()->PostDelayed(check_restore_backup_connection_interval_, this, | |
1488 MSG_CHECK_RESTORE_BACKUP_CONNECTION); | |
1489 } | |
1490 | |
1414 // Apart from sending ping from |conn| this method also updates | 1491 // Apart from sending ping from |conn| this method also updates |
1415 // |use_candidate_attr| flag. The criteria to update this flag is | 1492 // |use_candidate_attr| flag. The criteria to update this flag is |
1416 // explained below. | 1493 // explained below. |
1417 // Set USE-CANDIDATE if doing ICE AND this channel is in CONTROLLING AND | 1494 // Set USE-CANDIDATE if doing ICE AND this channel is in CONTROLLING AND |
1418 // a) Channel is in FULL ICE AND | 1495 // a) Channel is in FULL ICE AND |
1419 // a.1) |conn| is the best connection OR | 1496 // a.1) |conn| is the best connection OR |
1420 // a.2) there is no best connection OR | 1497 // a.2) there is no best connection OR |
1421 // a.3) the best connection is unwritable OR | 1498 // a.3) the best connection is unwritable OR |
1422 // a.4) |conn| has higher priority than best_connection. | 1499 // a.4) |conn| has higher priority than best_connection. |
1423 // b) we're doing LITE ICE AND | 1500 // b) we're doing LITE ICE AND |
(...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1455 | 1532 |
1456 // May stop the allocator session when at least one connection becomes | 1533 // May stop the allocator session when at least one connection becomes |
1457 // strongly connected after starting to get ports and the local candidate of | 1534 // strongly connected after starting to get ports and the local candidate of |
1458 // the connection is at the latest generation. It is not enough to check | 1535 // the connection is at the latest generation. It is not enough to check |
1459 // that the connection becomes weakly connected because the connection may be | 1536 // that the connection becomes weakly connected because the connection may be |
1460 // changing from (writable, receiving) to (writable, not receiving). | 1537 // changing from (writable, receiving) to (writable, not receiving). |
1461 bool strongly_connected = !connection->weak(); | 1538 bool strongly_connected = !connection->weak(); |
1462 bool latest_generation = connection->local_candidate().generation() >= | 1539 bool latest_generation = connection->local_candidate().generation() >= |
1463 allocator_session()->generation(); | 1540 allocator_session()->generation(); |
1464 if (strongly_connected && latest_generation) { | 1541 if (strongly_connected && latest_generation) { |
1542 if (recovering_start_time_) { | |
1543 recovering_start_time_ = 0; | |
1544 } | |
1465 MaybeStopPortAllocatorSessions(); | 1545 MaybeStopPortAllocatorSessions(); |
1466 } | 1546 } |
1467 | 1547 |
1468 // We have to unroll the stack before doing this because we may be changing | 1548 // We have to unroll the stack before doing this because we may be changing |
1469 // the state of connections while sorting. | 1549 // the state of connections while sorting. |
1470 RequestSort(); | 1550 RequestSort(); |
1471 } | 1551 } |
1472 | 1552 |
1473 // When a connection is removed, edit it out, and then update our best | 1553 // When a connection is removed, edit it out, and then update our best |
1474 // connection. | 1554 // connection. |
(...skipping 18 matching lines...) Expand all Loading... | |
1493 pending_best_connection_ = NULL; | 1573 pending_best_connection_ = NULL; |
1494 } | 1574 } |
1495 | 1575 |
1496 // If this is currently the best connection, then we need to pick a new one. | 1576 // If this is currently the best connection, then we need to pick a new one. |
1497 // The call to SortConnections will pick a new one. It looks at the current | 1577 // The call to SortConnections will pick a new one. It looks at the current |
1498 // best connection in order to avoid switching between fairly similar ones. | 1578 // best connection in order to avoid switching between fairly similar ones. |
1499 // Since this connection is no longer an option, we can just set best to NULL | 1579 // Since this connection is no longer an option, we can just set best to NULL |
1500 // and re-choose a best assuming that there was no best connection. | 1580 // and re-choose a best assuming that there was no best connection. |
1501 if (best_connection_ == connection) { | 1581 if (best_connection_ == connection) { |
1502 LOG(LS_INFO) << "Best connection destroyed. Will choose a new one."; | 1582 LOG(LS_INFO) << "Best connection destroyed. Will choose a new one."; |
1583 // When continual gathering is enabled, we will attempt re-gathering only | |
1584 // if the best connecion was removed and it was writable. If it was not | |
Taylor Brandstetter
2016/06/06 18:18:37
"connecion" => "connection"
honghaiz3
2016/06/07 16:42:06
Done.
| |
1585 // writable, most likely it is in the process of gathering on the current | |
1586 // session. | |
1587 if (config_.gather_continually && writable()) { | |
1588 bool all_connections_failed = std::all_of( | |
1589 connections_.begin(), connections_.end(), [](Connection* conn) { | |
1590 return conn->state() == Connection::STATE_FAILED; | |
1591 }); | |
1592 // Start regathering on all active networks if all connections failed. | |
1593 if (all_connections_failed && !IsRecoveringConnectivity()) { | |
1594 recovering_start_time_ = rtc::TimeMillis(); | |
1595 StartRegathering(nullptr); | |
1596 } | |
1597 } | |
1503 SwitchBestConnectionTo(NULL); | 1598 SwitchBestConnectionTo(NULL); |
1504 RequestSort(); | 1599 RequestSort(); |
1505 } | 1600 } |
1506 | 1601 |
1507 UpdateState(); | 1602 UpdateState(); |
1508 } | 1603 } |
1509 | 1604 |
1510 // When a port is destroyed remove it from our list of ports to use for | 1605 // When a port is destroyed remove it from our list of ports to use for |
1511 // connection attempts. | 1606 // connection attempts. |
1512 void P2PTransportChannel::OnPortDestroyed(PortInterface* port) { | 1607 void P2PTransportChannel::OnPortDestroyed(PortInterface* port) { |
1513 ASSERT(worker_thread_ == rtc::Thread::Current()); | 1608 ASSERT(worker_thread_ == rtc::Thread::Current()); |
1514 | 1609 |
1515 // Remove this port from the list (if we didn't drop it already). | 1610 // Remove this port from the list (if we didn't drop it already). |
1516 std::vector<PortInterface*>::iterator iter = | 1611 std::vector<PortInterface*>::iterator iter = |
1517 std::find(ports_.begin(), ports_.end(), port); | 1612 std::find(ports_.begin(), ports_.end(), port); |
1518 if (iter != ports_.end()) | 1613 if (iter != ports_.end()) |
1519 ports_.erase(iter); | 1614 ports_.erase(iter); |
1520 | 1615 |
1521 LOG(INFO) << "Removed port from p2p socket: " | 1616 LOG(INFO) << "Removed port from p2p socket: " |
1522 << static_cast<int>(ports_.size()) << " remaining"; | 1617 << static_cast<int>(ports_.size()) << " remaining"; |
1523 } | 1618 } |
1524 | 1619 |
1525 void P2PTransportChannel::OnPortNetworkInactive(PortInterface* port) { | 1620 void P2PTransportChannel::OnPortNetworkInactive(PortInterface* port) { |
1526 // If it does not gather continually, the port will be removed from the list | 1621 // If it does not gather continually, the port will be removed from the list |
1527 // when ICE restarts. | 1622 // when ICE restarts, so don't need to remove it here. |
1528 if (!config_.gather_continually) { | 1623 if (!config_.gather_continually) { |
1529 return; | 1624 return; |
1530 } | 1625 } |
1531 auto it = std::find(ports_.begin(), ports_.end(), port); | 1626 auto it = std::find(ports_.begin(), ports_.end(), port); |
1532 // Don't need to do anything if the port has been deleted from the port list. | 1627 // Don't need to do anything if the port has been deleted from the port list. |
1533 if (it == ports_.end()) { | 1628 if (it == ports_.end()) { |
1534 return; | 1629 return; |
1535 } | 1630 } |
1536 ports_.erase(it); | 1631 ports_.erase(it); |
1537 LOG(INFO) << "Removed port due to inactive networks: " << ports_.size() | 1632 LOG(INFO) << "Removed port due to inactive networks: " << ports_.size() |
1538 << " remaining"; | 1633 << " remaining"; |
1539 std::vector<Candidate> candidates = port->Candidates(); | 1634 port->FailAndDestroyConnections(); |
1540 for (Candidate& candidate : candidates) { | 1635 |
1636 for (Candidate candidate : port->Candidates()) { | |
1541 candidate.set_transport_name(transport_name()); | 1637 candidate.set_transport_name(transport_name()); |
1638 candidates_removed_.push_back(candidate); | |
Taylor Brandstetter
2016/06/06 18:18:37
Something I didn't notice until now: This needs to
honghaiz3
2016/06/07 16:42:06
Done.
| |
1542 } | 1639 } |
1543 SignalCandidatesRemoved(this, candidates); | 1640 thread()->Post(this, MSG_SIGNAL_CANDIDATES_REMOVED); |
1641 } | |
1642 | |
1643 void P2PTransportChannel::StartRegathering( | |
1644 std::vector<rtc::Network*>* networks) { | |
1645 std::string log_msg; | |
1646 std::vector<PortInterface*> ports_to_remove; | |
1647 if (networks == nullptr) { | |
1648 log_msg = "Regathering on all networks"; | |
1649 ports_to_remove = ports_; | |
1650 } else { | |
1651 log_msg = "Regathering on networks:"; | |
1652 for (rtc::Network* network : *networks) { | |
1653 log_msg += " " + network->ToString(); | |
1654 } | |
1655 // Remove all ports using |networks|. | |
1656 for (PortInterface* port : ports_) { | |
1657 if (std::find(networks->begin(), networks->end(), port->Network()) != | |
1658 networks->end()) { | |
1659 ports_to_remove.push_back(port); | |
1660 } | |
1661 } | |
1662 } | |
1663 LOG(LS_INFO) << log_msg; | |
1664 for (PortInterface* port : ports_to_remove) { | |
1665 // Remove the port and signal the other side to remove the respective remote | |
1666 // candidates. | |
1667 OnPortNetworkInactive(port); | |
1668 } | |
1669 | |
1670 PortAllocatorSession* session = allocator_session(); | |
1671 // By deactivating all networks in existing allocation sequences, | |
1672 // it will force re-gathering on all active networks. | |
1673 session->InactivateNetworksInExistingSequences(networks); | |
1674 session->StartGettingPorts(); | |
1544 } | 1675 } |
1545 | 1676 |
1546 // We data is available, let listeners know | 1677 // We data is available, let listeners know |
1547 void P2PTransportChannel::OnReadPacket(Connection* connection, | 1678 void P2PTransportChannel::OnReadPacket(Connection* connection, |
1548 const char* data, | 1679 const char* data, |
1549 size_t len, | 1680 size_t len, |
1550 const rtc::PacketTime& packet_time) { | 1681 const rtc::PacketTime& packet_time) { |
1551 ASSERT(worker_thread_ == rtc::Thread::Current()); | 1682 ASSERT(worker_thread_ == rtc::Thread::Current()); |
1552 | 1683 |
1553 // Do not deliver, if packet doesn't belong to the correct transport channel. | 1684 // Do not deliver, if packet doesn't belong to the correct transport channel. |
(...skipping 134 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1688 | 1819 |
1689 // During the initial state when nothing has been pinged yet, return the first | 1820 // During the initial state when nothing has been pinged yet, return the first |
1690 // one in the ordered |connections_|. | 1821 // one in the ordered |connections_|. |
1691 return *(std::find_if(connections_.begin(), connections_.end(), | 1822 return *(std::find_if(connections_.begin(), connections_.end(), |
1692 [conn1, conn2](Connection* conn) { | 1823 [conn1, conn2](Connection* conn) { |
1693 return conn == conn1 || conn == conn2; | 1824 return conn == conn1 || conn == conn2; |
1694 })); | 1825 })); |
1695 } | 1826 } |
1696 | 1827 |
1697 } // namespace cricket | 1828 } // namespace cricket |
OLD | NEW |