Chromium Code Reviews| Index: webrtc/p2p/client/basicportallocator.cc |
| diff --git a/webrtc/p2p/client/basicportallocator.cc b/webrtc/p2p/client/basicportallocator.cc |
| index e39a44013cdcf4f5b4cf627e225c499afb1e1687..1789727dcfb2cc369794c59709b31618492c9c17 100644 |
| --- a/webrtc/p2p/client/basicportallocator.cc |
| +++ b/webrtc/p2p/client/basicportallocator.cc |
| @@ -215,6 +215,59 @@ void BasicPortAllocatorSession::ClearGettingPorts() { |
| sequences_[i]->Stop(); |
| } |
| +std::vector<rtc::Network*> BasicPortAllocatorSession::GetFailedNetworks() { |
| + std::vector<rtc::Network*> networks = GetNetworks(); |
| + |
| + // A network interface may have both IPv4 and IPv6 networks. Only if |
| + // neither of the networks has any connections, the network interface |
| + // is considered failed and need to be regathered on. |
| + std::set<std::string> networks_having_connection; |
|
pthatcher1
2016/06/29 21:34:12
networks_with_connections would be a better name.
honghaiz3
2016/06/30 01:04:22
Done.
|
| + for (const PortData& data : ports_) { |
| + Port* port = data.port(); |
| + if (!port->connections().empty()) { |
| + networks_having_connection.insert(port->Network()->name()); |
| + } |
| + } |
| + |
| + networks.erase( |
| + std::remove_if(networks.begin(), networks.end(), |
| + [networks_having_connection](rtc::Network* network) { |
| + // If a network does not have any connection, it is |
| + // considered failed. |
|
Taylor Brandstetter
2016/06/29 22:12:27
What if a connection just hasn't been made yet?
honghaiz3
2016/06/30 01:04:22
This is a good point.
I added an enum SessionStat
honghaiz3
2016/06/30 04:49:45
To elaborate it a little bit, that could only happ
|
| + return networks_having_connection.find( |
| + network->name()) != |
| + networks_having_connection.end(); |
| + }), |
| + networks.end()); |
| + return networks; |
| +} |
| + |
| +void BasicPortAllocatorSession::RegatherOnFailedNetworks() { |
| + // Find the list of networks that have no connection. |
| + std::vector<rtc::Network*> failed_networks = GetFailedNetworks(); |
| + if (failed_networks.empty()) { |
| + return; |
| + } |
| + |
| + // Mark a sequence as "network failed" if its network in the list of failed |
|
Taylor Brandstetter
2016/06/29 22:12:27
"if its network is in the..."
honghaiz3
2016/06/30 01:04:22
Done.
|
| + // networks, so that it won't be considered as equivalent when the session |
| + // regathers ports and candidates. |
| + for (AllocationSequence* sequence : sequences_) { |
| + if (!sequence->network_failed() && |
| + std::find(failed_networks.begin(), failed_networks.end(), |
| + sequence->network()) != failed_networks.end()) { |
| + sequence->set_network_failed(); |
| + } |
| + } |
| + // Remove ports from being used locally and send signaling to remove |
| + // the candidates on the remote side. |
| + RemovePortsAndCandidates(failed_networks); |
| + |
| + if (allocation_started_ && network_manager_started_) { |
| + DoAllocate(); |
| + } |
| +} |
| + |
| std::vector<PortInterface*> BasicPortAllocatorSession::ReadyPorts() const { |
| std::vector<PortInterface*> ret; |
| for (const PortData& port : ports_) { |
| @@ -228,21 +281,28 @@ std::vector<PortInterface*> BasicPortAllocatorSession::ReadyPorts() const { |
| std::vector<Candidate> BasicPortAllocatorSession::ReadyCandidates() const { |
| std::vector<Candidate> candidates; |
| for (const PortData& data : ports_) { |
| - for (const Candidate& candidate : data.port()->Candidates()) { |
| - if (!CheckCandidateFilter(candidate)) { |
| - continue; |
| - } |
| - ProtocolType pvalue; |
| - if (!StringToProto(candidate.protocol().c_str(), &pvalue) || |
| - !data.sequence()->ProtocolEnabled(pvalue)) { |
| - continue; |
| - } |
| - candidates.push_back(SanitizeRelatedAddress(candidate)); |
| - } |
| + GetCandidatesFromPort(data, &candidates); |
| } |
| return candidates; |
| } |
| +void BasicPortAllocatorSession::GetCandidatesFromPort( |
| + const PortData& data, |
| + std::vector<Candidate>* candidates) const { |
| + RTC_CHECK(candidates != nullptr); |
| + for (const Candidate& candidate : data.port()->Candidates()) { |
| + if (!CheckCandidateFilter(candidate)) { |
| + continue; |
| + } |
| + ProtocolType pvalue; |
| + if (!StringToProto(candidate.protocol().c_str(), &pvalue) || |
| + !data.sequence()->ProtocolEnabled(pvalue)) { |
| + continue; |
| + } |
| + candidates->push_back(SanitizeRelatedAddress(candidate)); |
| + } |
| +} |
| + |
| Candidate BasicPortAllocatorSession::SanitizeRelatedAddress( |
| const Candidate& c) const { |
| Candidate copy = c; |
| @@ -391,9 +451,8 @@ void BasicPortAllocatorSession::OnAllocate() { |
| allocation_started_ = true; |
| } |
| -void BasicPortAllocatorSession::GetNetworks( |
| - std::vector<rtc::Network*>* networks) { |
| - networks->clear(); |
| +std::vector<rtc::Network*> BasicPortAllocatorSession::GetNetworks() { |
| + std::vector<rtc::Network*> networks; |
| rtc::NetworkManager* network_manager = allocator_->network_manager(); |
| ASSERT(network_manager != nullptr); |
| // If the network permission state is BLOCKED, we just act as if the flag has |
| @@ -407,37 +466,37 @@ void BasicPortAllocatorSession::GetNetworks( |
| // traffic by OS is also used here to avoid any local or public IP leakage |
| // during stun process. |
| if (flags() & PORTALLOCATOR_DISABLE_ADAPTER_ENUMERATION) { |
| - network_manager->GetAnyAddressNetworks(networks); |
| + network_manager->GetAnyAddressNetworks(&networks); |
| } else { |
| - network_manager->GetNetworks(networks); |
| + network_manager->GetNetworks(&networks); |
| } |
| - networks->erase(std::remove_if(networks->begin(), networks->end(), |
| - [this](rtc::Network* network) { |
| - return allocator_->network_ignore_mask() & |
| - network->type(); |
| - }), |
| - networks->end()); |
| + networks.erase(std::remove_if(networks.begin(), networks.end(), |
| + [this](rtc::Network* network) { |
| + return allocator_->network_ignore_mask() & |
| + network->type(); |
| + }), |
| + networks.end()); |
| if (flags() & PORTALLOCATOR_DISABLE_COSTLY_NETWORKS) { |
| uint16_t lowest_cost = rtc::kNetworkCostMax; |
| - for (rtc::Network* network : *networks) { |
| + for (rtc::Network* network : networks) { |
| lowest_cost = std::min<uint16_t>(lowest_cost, network->GetCost()); |
| } |
| - networks->erase(std::remove_if(networks->begin(), networks->end(), |
| - [lowest_cost](rtc::Network* network) { |
| - return network->GetCost() > |
| - lowest_cost + rtc::kNetworkCostLow; |
| - }), |
| - networks->end()); |
| + networks.erase(std::remove_if(networks.begin(), networks.end(), |
| + [lowest_cost](rtc::Network* network) { |
| + return network->GetCost() > |
| + lowest_cost + rtc::kNetworkCostLow; |
| + }), |
| + networks.end()); |
| } |
| + return networks; |
| } |
| // For each network, see if we have a sequence that covers it already. If not, |
| // create a new sequence to create the appropriate ports. |
| void BasicPortAllocatorSession::DoAllocate() { |
| bool done_signal_needed = false; |
| - std::vector<rtc::Network*> networks; |
| - GetNetworks(&networks); |
| + std::vector<rtc::Network*> networks = GetNetworks(); |
| if (networks.empty()) { |
| LOG(LS_WARNING) << "Machine has no networks; no ports will be allocated"; |
| @@ -485,8 +544,9 @@ void BasicPortAllocatorSession::DoAllocate() { |
| done_signal_needed = true; |
| sequence->SignalPortAllocationComplete.connect( |
| this, &BasicPortAllocatorSession::OnPortAllocationComplete); |
| - if (running_) |
| + if (running_) { |
| sequence->Start(); |
| + } |
| sequences_.push_back(sequence); |
| } |
| } |
| @@ -496,17 +556,19 @@ void BasicPortAllocatorSession::DoAllocate() { |
| } |
| void BasicPortAllocatorSession::OnNetworksChanged() { |
| - std::vector<rtc::Network*> networks; |
| - GetNetworks(&networks); |
| + std::vector<rtc::Network*> networks = GetNetworks(); |
| + std::vector<rtc::Network*> failed_networks; |
| for (AllocationSequence* sequence : sequences_) { |
| // Remove the network from the allocation sequence if it is not in |
| // |networks|. |
| - if (!sequence->network_removed() && |
| + if (!sequence->network_failed() && |
| std::find(networks.begin(), networks.end(), sequence->network()) == |
| networks.end()) { |
| - sequence->OnNetworkRemoved(); |
| + sequence->OnNetworkFailed(); |
| + failed_networks.push_back(sequence->network()); |
| } |
| } |
| + RemovePortsAndCandidates(failed_networks); |
| network_manager_started_ = true; |
| if (allocation_started_) |
| @@ -756,6 +818,23 @@ BasicPortAllocatorSession::PortData* BasicPortAllocatorSession::FindPort( |
| return NULL; |
| } |
| +// Removes ports and candidates created on a given list of networks. |
| +void BasicPortAllocatorSession::RemovePortsAndCandidates( |
| + const std::vector<rtc::Network*>& networks) { |
| + std::vector<PortInterface*> ports_to_remove; |
| + std::vector<Candidate> candidates_to_remove; |
| + for (const PortData& data : ports_) { |
| + if (std::find(networks.begin(), networks.end(), |
| + data.sequence()->network()) == networks.end()) { |
| + continue; |
| + } |
| + ports_to_remove.push_back(data.port()); |
| + GetCandidatesFromPort(data, &candidates_to_remove); |
| + } |
| + SignalPortsRemoved(this, ports_to_remove); |
| + SignalCandidatesRemoved(this, candidates_to_remove); |
| +} |
| + |
| // AllocationSequence |
| AllocationSequence::AllocationSequence(BasicPortAllocatorSession* session, |
| @@ -793,10 +872,11 @@ void AllocationSequence::Clear() { |
| turn_ports_.clear(); |
| } |
| -void AllocationSequence::OnNetworkRemoved() { |
| - // Stop the allocation sequence if its network is gone. |
| +void AllocationSequence::OnNetworkFailed() { |
| + RTC_DCHECK(!network_failed_); |
| + network_failed_ = true; |
| + // Stop the allocation sequence if its network failed. |
| Stop(); |
| - network_removed_ = true; |
| } |
| AllocationSequence::~AllocationSequence() { |
| @@ -805,8 +885,8 @@ AllocationSequence::~AllocationSequence() { |
| void AllocationSequence::DisableEquivalentPhases(rtc::Network* network, |
| PortConfiguration* config, uint32_t* flags) { |
| - if (network_removed_) { |
| - // If the network of this allocation sequence has ever gone away, |
| + if (network_failed_) { |
| + // If the network of this allocation sequence has ever become failed, |
| // it won't be equivalent to the new network. |
| return; |
| } |