| 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
|
|
|