Index: webrtc/p2p/base/p2ptransportchannel.cc |
diff --git a/webrtc/p2p/base/p2ptransportchannel.cc b/webrtc/p2p/base/p2ptransportchannel.cc |
index d83726eab5a5b53c1af9edbda62f93907ac5e22c..032d9186ef46e270b96ed1a283543f86a0ae578d 100644 |
--- a/webrtc/p2p/base/p2ptransportchannel.cc |
+++ b/webrtc/p2p/base/p2ptransportchannel.cc |
@@ -27,10 +27,15 @@ |
namespace { |
// messages for queuing up work for ourselves |
-enum { MSG_SORT = 1, MSG_CHECK_AND_PING }; |
+enum { |
+ MSG_SORT = 1, |
+ MSG_CHECK_AND_PING, |
+ MSG_REGATHER_ON_FAILED_NETWORKS, |
+ MSG_SIGNAL_CANDIDATES_REMOVED |
+}; |
// The minimum improvement in RTT that justifies a switch. |
-static const double kMinImprovement = 10; |
+const double kMinImprovement = 10; |
bool IsRelayRelay(cricket::Connection* conn) { |
return conn->local_candidate().type() == cricket::RELAY_PORT_TYPE && |
@@ -224,6 +229,10 @@ static const int MAX_CURRENT_STRONG_INTERVAL = 900; // ms |
static const int MIN_CHECK_RECEIVING_INTERVAL = 50; // ms |
+// We periodically check if any existing networks do not have any connection |
+// and regather on those failed networks. |
+static const int DEFAULT_REGATHER_ON_FAILED_NETWORKS_INTERVAL = 5 * 60 * 1000; |
+ |
P2PTransportChannel::P2PTransportChannel(const std::string& transport_name, |
int component, |
P2PTransport* transport, |
@@ -246,11 +255,13 @@ P2PTransportChannel::P2PTransportChannel(const std::string& transport_name, |
tiebreaker_(0), |
gathering_state_(kIceGatheringNew), |
check_receiving_interval_(MIN_CHECK_RECEIVING_INTERVAL * 5), |
- config_(MIN_CHECK_RECEIVING_INTERVAL * 50 /* receiving_timeout */, |
- 0 /* backup_connection_ping_interval */, |
- false /* gather_continually */, |
- false /* prioritize_most_likely_candidate_pairs */, |
- MAX_CURRENT_STRONG_INTERVAL /* max_strong_interval */) { |
+ config_( |
+ MIN_CHECK_RECEIVING_INTERVAL * 50 /* receiving_timeout */, |
+ 0 /* backup_connection_ping_interval */, |
+ GATHER_ONCE, |
+ false /* prioritize_most_likely_candidate_pairs */, |
+ MAX_CURRENT_STRONG_INTERVAL /* max_strong_interval */, |
+ DEFAULT_REGATHER_ON_FAILED_NETWORKS_INTERVAL) { |
uint32_t weak_ping_interval = ::strtoul( |
webrtc::field_trial::FindFullName("WebRTC-StunInterPacketDelay").c_str(), |
nullptr, 10); |
@@ -273,6 +284,8 @@ void P2PTransportChannel::AddAllocatorSession( |
session->SignalPortReady.connect(this, &P2PTransportChannel::OnPortReady); |
session->SignalCandidatesReady.connect( |
this, &P2PTransportChannel::OnCandidatesReady); |
+ session->SignalCandidatesRemoved.connect( |
+ this, &P2PTransportChannel::OnCandidatesRemoved); |
session->SignalCandidatesAllocationDone.connect( |
this, &P2PTransportChannel::OnCandidatesAllocationDone); |
@@ -402,8 +415,8 @@ void P2PTransportChannel::SetRemoteIceMode(IceMode mode) { |
} |
void P2PTransportChannel::SetIceConfig(const IceConfig& config) { |
- config_.gather_continually = config.gather_continually; |
- LOG(LS_INFO) << "Set gather_continually to " << config_.gather_continually; |
+ config_.gathering_policy = config.gathering_policy; |
+ LOG(LS_INFO) << "Set gathering_policy to " << config_.gathering_policy; |
if (config.backup_connection_ping_interval >= 0 && |
config_.backup_connection_ping_interval != |
@@ -438,6 +451,15 @@ void P2PTransportChannel::SetIceConfig(const IceConfig& config) { |
LOG(LS_INFO) << "Set max strong interval to " |
<< config_.max_strong_interval; |
} |
+ |
+ if (config.regather_on_failed_networks_interval >= 0 && |
+ config.regather_on_failed_networks_interval != |
+ config_.regather_on_failed_networks_interval) { |
+ config_.regather_on_failed_networks_interval = |
+ config.regather_on_failed_networks_interval; |
+ LOG(LS_INFO) << "Set regather_on_failed_networks_interval to " |
+ << config_.regather_on_failed_networks_interval; |
+ } |
} |
const IceConfig& P2PTransportChannel::config() const { |
@@ -456,6 +478,9 @@ void P2PTransportChannel::Connect() { |
// Start checking and pinging as the ports come in. |
thread()->Post(RTC_FROM_HERE, this, MSG_CHECK_AND_PING); |
+ thread()->PostDelayed(RTC_FROM_HERE, |
+ config_.regather_on_failed_networks_interval, this, |
+ MSG_REGATHER_ON_FAILED_NETWORKS); |
} |
void P2PTransportChannel::MaybeStartGathering() { |
@@ -520,8 +545,8 @@ void P2PTransportChannel::OnPortReady(PortAllocatorSession *session, |
port->SignalUnknownAddress.connect( |
this, &P2PTransportChannel::OnUnknownAddress); |
port->SignalDestroyed.connect(this, &P2PTransportChannel::OnPortDestroyed); |
- port->SignalNetworkInactive.connect( |
- this, &P2PTransportChannel::OnPortNetworkInactive); |
+ port->SignalClosed.connect(this, &P2PTransportChannel::OnPortClosed); |
+ |
port->SignalRoleConflict.connect( |
this, &P2PTransportChannel::OnRoleConflict); |
port->SignalSentPacket.connect(this, &P2PTransportChannel::OnSentPacket); |
@@ -1256,16 +1281,17 @@ void P2PTransportChannel::MaybeStopPortAllocatorSessions() { |
} |
for (const auto& session : allocator_sessions_) { |
- if (!session->IsGettingPorts()) { |
+ if (!session->CanGetPorts()) { |
+ // The session has completely stopped. |
continue; |
} |
- // If gathering continually, keep the last session running so that it |
- // will gather candidates if the networks change. |
- if (config_.gather_continually && session == allocator_sessions_.back()) { |
+ // If gathering continually, keep the last session at STATE_CLEARED so that |
+ // it can gather candidates if the networks change. |
+ if (config_.gather_continually() && session == allocator_sessions_.back()) { |
session->ClearGettingPorts(); |
- break; |
+ } else { |
+ session->StopGettingPorts(); |
} |
- session->StopGettingPorts(); |
} |
} |
@@ -1306,6 +1332,17 @@ void P2PTransportChannel::OnMessage(rtc::Message *pmsg) { |
case MSG_CHECK_AND_PING: |
OnCheckAndPing(); |
break; |
+ case MSG_REGATHER_ON_FAILED_NETWORKS: |
+ RegatherOnFailedNetworks(); |
+ break; |
+ case MSG_SIGNAL_CANDIDATES_REMOVED: |
+ if (!candidates_to_remove_.empty()) { |
+ LOG(LS_INFO) << "Signal removing " << candidates_to_remove_.size() |
+ << " candidates"; |
+ SignalCandidatesRemoved(this, candidates_to_remove_); |
+ candidates_to_remove_.clear(); |
+ } |
+ break; |
default: |
ASSERT(false); |
break; |
@@ -1507,40 +1544,65 @@ void P2PTransportChannel::OnConnectionDestroyed(Connection* connection) { |
UpdateState(); |
} |
-// When a port is destroyed remove it from our list of ports to use for |
-// connection attempts. |
void P2PTransportChannel::OnPortDestroyed(PortInterface* port) { |
ASSERT(worker_thread_ == rtc::Thread::Current()); |
- // Remove this port from the list (if we didn't drop it already). |
- std::vector<PortInterface*>::iterator iter = |
- std::find(ports_.begin(), ports_.end(), port); |
- if (iter != ports_.end()) |
- ports_.erase(iter); |
+ if (RemovePort(port)) { |
+ LOG(INFO) << "Removed port because it is destroyed: " << ports_.size() |
+ << " remaining"; |
+ } |
+} |
+ |
+void P2PTransportChannel::OnPortClosed(PortInterface* port) { |
+ ASSERT(worker_thread_ == rtc::Thread::Current()); |
- LOG(INFO) << "Removed port from p2p socket: " |
- << static_cast<int>(ports_.size()) << " remaining"; |
+ if (RemovePort(port)) { |
+ LOG(INFO) << "Removed port because it is closed: " << ports_.size() |
+ << " remaining"; |
+ } |
} |
-void P2PTransportChannel::OnPortNetworkInactive(PortInterface* port) { |
- // If it does not gather continually, the port will be removed from the list |
- // when ICE restarts. |
- if (!config_.gather_continually) { |
- return; |
+bool P2PTransportChannel::RemovePort(PortInterface* port) { |
+ auto new_end = std::remove(ports_.begin(), ports_.end(), port); |
+ if (new_end != ports_.end()) { |
+ ports_.erase(new_end, ports_.end()); |
+ return true; |
} |
- auto it = std::find(ports_.begin(), ports_.end(), port); |
- // Don't need to do anything if the port has been deleted from the port list. |
- if (it == ports_.end()) { |
+ return false; |
+} |
+ |
+void P2PTransportChannel::OnCandidatesRemoved( |
+ PortAllocatorSession* session, |
+ const std::vector<Candidate>& candidates) { |
+ ASSERT(worker_thread_ == rtc::Thread::Current()); |
+ // Do not signal candidate removals if continual gathering is not enabled. |
+ // Do not signal candidate removals if this is not the last session because |
+ // an ICE restart would have signaled the remote side about all candidate |
+ // removals in previous sessions. |
+ if (!config_.gather_continually() || session != allocator_session()) { |
return; |
} |
- ports_.erase(it); |
- LOG(INFO) << "Removed port due to inactive networks: " << ports_.size() |
- << " remaining"; |
- std::vector<Candidate> candidates = port->Candidates(); |
- for (Candidate& candidate : candidates) { |
+ |
+ // If |candidates_to_remove_| is not empty, a msg |
+ // MSG_SIGNAL_CANDIDATES_REMOVED should have been posted. |
+ if (candidates_to_remove_.empty()) { |
+ thread()->Post(this, MSG_SIGNAL_CANDIDATES_REMOVED); |
+ } |
+ |
+ for (Candidate candidate : candidates) { |
candidate.set_transport_name(transport_name()); |
+ candidates_to_remove_.push_back(candidate); |
} |
- SignalCandidatesRemoved(this, candidates); |
+} |
+ |
+void P2PTransportChannel::OnRegatherOnFailedNetworks() { |
+ if (!config_.gather_continually() || allocator_sessions_.empty()) { |
+ return; |
+ } |
+ allocator_session()->RegatherOnFailedNetworks(); |
+ |
+ thread()->PostDelayed(config_.regather_on_failed_network_interval_, this, |
+ MSG_REGATHER_ON_FAILED_NETWORKS); |
} |
// We data is available, let listeners know |