Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(64)

Side by Side Diff: webrtc/p2p/client/basicportallocator.cc

Issue 1998813002: Fixing the behavior of the candidate filter with pooled candidates. (Closed) Base URL: https://chromium.googlesource.com/external/webrtc.git@master
Patch Set: Created 4 years, 7 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
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
(...skipping 158 matching lines...) Expand 10 before | Expand all | Expand 10 after
169 for (it = ports_.begin(); it != ports_.end(); it++) 169 for (it = ports_.begin(); it != ports_.end(); it++)
170 delete it->port(); 170 delete it->port();
171 171
172 for (uint32_t i = 0; i < configs_.size(); ++i) 172 for (uint32_t i = 0; i < configs_.size(); ++i)
173 delete configs_[i]; 173 delete configs_[i];
174 174
175 for (uint32_t i = 0; i < sequences_.size(); ++i) 175 for (uint32_t i = 0; i < sequences_.size(); ++i)
176 delete sequences_[i]; 176 delete sequences_[i];
177 } 177 }
178 178
179 void BasicPortAllocatorSession::SetCandidateFilter(uint32_t filter) {
180 if (filter == candidate_filter_) {
181 return;
182 }
183 // We assume the filter will only change from "ALL" to something else.
184 RTC_DCHECK(candidate_filter_ == CF_ALL);
185 candidate_filter_ = filter;
186 for (PortData& port : ports_) {
187 if (!port.ready()) {
188 continue;
189 }
190 const auto& candidates = port.port()->Candidates();
191 // Setting a filter may cause a ready port to become non-ready
192 // if it suddenly has no pairable candidates.
193 if (!std::any_of(candidates.begin(), candidates.end(),
194 [this, &port](const Candidate& candidate) {
195 return CandidatePairable(candidate, port.port());
196 })) {
197 port.set_ready(false);
198 }
199 }
200 }
201
179 void BasicPortAllocatorSession::StartGettingPorts() { 202 void BasicPortAllocatorSession::StartGettingPorts() {
180 network_thread_ = rtc::Thread::Current(); 203 network_thread_ = rtc::Thread::Current();
181 if (!socket_factory_) { 204 if (!socket_factory_) {
182 owned_socket_factory_.reset( 205 owned_socket_factory_.reset(
183 new rtc::BasicPacketSocketFactory(network_thread_)); 206 new rtc::BasicPacketSocketFactory(network_thread_));
184 socket_factory_ = owned_socket_factory_.get(); 207 socket_factory_ = owned_socket_factory_.get();
185 } 208 }
186 209
187 running_ = true; 210 running_ = true;
188 network_thread_->Post(this, MSG_CONFIG_START); 211 network_thread_->Post(this, MSG_CONFIG_START);
(...skipping 11 matching lines...) Expand all
200 223
201 void BasicPortAllocatorSession::ClearGettingPorts() { 224 void BasicPortAllocatorSession::ClearGettingPorts() {
202 network_thread_->Clear(this, MSG_ALLOCATE); 225 network_thread_->Clear(this, MSG_ALLOCATE);
203 for (uint32_t i = 0; i < sequences_.size(); ++i) 226 for (uint32_t i = 0; i < sequences_.size(); ++i)
204 sequences_[i]->Stop(); 227 sequences_[i]->Stop();
205 } 228 }
206 229
207 std::vector<PortInterface*> BasicPortAllocatorSession::ReadyPorts() const { 230 std::vector<PortInterface*> BasicPortAllocatorSession::ReadyPorts() const {
208 std::vector<PortInterface*> ret; 231 std::vector<PortInterface*> ret;
209 for (const PortData& port : ports_) { 232 for (const PortData& port : ports_) {
210 if (port.ready() || port.complete()) { 233 if (port.ready() && !port.error()) {
211 ret.push_back(port.port()); 234 ret.push_back(port.port());
212 } 235 }
213 } 236 }
214 return ret; 237 return ret;
215 } 238 }
216 239
217 std::vector<Candidate> BasicPortAllocatorSession::ReadyCandidates() const { 240 std::vector<Candidate> BasicPortAllocatorSession::ReadyCandidates() const {
218 std::vector<Candidate> candidates; 241 std::vector<Candidate> candidates;
219 for (const PortData& data : ports_) { 242 for (const PortData& data : ports_) {
220 for (const Candidate& candidate : data.port()->Candidates()) { 243 for (const Candidate& candidate : data.port()->Candidates()) {
221 if (!CheckCandidateFilter(candidate)) { 244 if (!CheckCandidateFilter(candidate)) {
222 continue; 245 continue;
223 } 246 }
224 ProtocolType pvalue; 247 ProtocolType pvalue;
225 if (!StringToProto(candidate.protocol().c_str(), &pvalue) || 248 if (!StringToProto(candidate.protocol().c_str(), &pvalue) ||
226 !data.sequence()->ProtocolEnabled(pvalue)) { 249 !data.sequence()->ProtocolEnabled(pvalue)) {
227 continue; 250 continue;
228 } 251 }
229 candidates.push_back(candidate); 252 candidates.push_back(SanitizeRelatedAddress(candidate));
230 } 253 }
231 } 254 }
232 return candidates; 255 return candidates;
233 } 256 }
234 257
258 Candidate BasicPortAllocatorSession::SanitizeRelatedAddress(
259 const Candidate& c) const {
260 Candidate copy = c;
261 // If adapter enumeration is disabled or host candidates are disabled,
262 // clear the raddr of STUN candidates to avoid local address leakage.
263 bool filter_stun_related_address =
264 ((flags() & PORTALLOCATOR_DISABLE_ADAPTER_ENUMERATION) &&
265 (flags() & PORTALLOCATOR_DISABLE_DEFAULT_LOCAL_CANDIDATE)) ||
266 !(candidate_filter_ & CF_HOST);
267 // If the candidate filter doesn't allow reflexive addresses, empty TURN raddr
268 // to avoid reflexive address leakage.
269 bool filter_turn_related_address = !(candidate_filter_ & CF_REFLEXIVE);
270 if ((c.type() == STUN_PORT_TYPE && filter_stun_related_address) ||
271 (c.type() == RELAY_PORT_TYPE && filter_turn_related_address)) {
272 copy.set_related_address(
273 rtc::EmptySocketAddressWithFamily(copy.address().family()));
274 }
275 return copy;
276 }
277
235 bool BasicPortAllocatorSession::CandidatesAllocationDone() const { 278 bool BasicPortAllocatorSession::CandidatesAllocationDone() const {
236 // Done only if all required AllocationSequence objects 279 // Done only if all required AllocationSequence objects
237 // are created. 280 // are created.
238 if (!allocation_sequences_created_) { 281 if (!allocation_sequences_created_) {
239 return false; 282 return false;
240 } 283 }
241 284
242 // Check that all port allocation sequences are complete (not running). 285 // Check that all port allocation sequences are complete (not running).
243 if (std::any_of(sequences_.begin(), sequences_.end(), 286 if (std::any_of(sequences_.begin(), sequences_.end(),
244 [](const AllocationSequence* sequence) { 287 [](const AllocationSequence* sequence) {
(...skipping 250 matching lines...) Expand 10 before | Expand all | Expand 10 after
495 538
496 LOG(LS_INFO) << "Adding allocated port for " << content_name(); 539 LOG(LS_INFO) << "Adding allocated port for " << content_name();
497 port->set_content_name(content_name()); 540 port->set_content_name(content_name());
498 port->set_component(component()); 541 port->set_component(component());
499 port->set_generation(generation()); 542 port->set_generation(generation());
500 if (allocator_->proxy().type != rtc::PROXY_NONE) 543 if (allocator_->proxy().type != rtc::PROXY_NONE)
501 port->set_proxy(allocator_->user_agent(), allocator_->proxy()); 544 port->set_proxy(allocator_->user_agent(), allocator_->proxy());
502 port->set_send_retransmit_count_attribute( 545 port->set_send_retransmit_count_attribute(
503 (flags() & PORTALLOCATOR_ENABLE_STUN_RETRANSMIT_ATTRIBUTE) != 0); 546 (flags() & PORTALLOCATOR_ENABLE_STUN_RETRANSMIT_ATTRIBUTE) != 0);
504 547
505 // Push down the candidate_filter to individual port.
506 uint32_t candidate_filter = allocator_->candidate_filter();
507
508 // When adapter enumeration is disabled, disable CF_HOST at port level so
509 // local address is not leaked by stunport in the candidate's related address.
510 if ((flags() & PORTALLOCATOR_DISABLE_ADAPTER_ENUMERATION) &&
511 (flags() & PORTALLOCATOR_DISABLE_DEFAULT_LOCAL_CANDIDATE)) {
512 candidate_filter &= ~CF_HOST;
513 }
514 port->set_candidate_filter(candidate_filter);
515
516 PortData data(port, seq); 548 PortData data(port, seq);
517 ports_.push_back(data); 549 ports_.push_back(data);
518 550
519 port->SignalCandidateReady.connect( 551 port->SignalCandidateReady.connect(
520 this, &BasicPortAllocatorSession::OnCandidateReady); 552 this, &BasicPortAllocatorSession::OnCandidateReady);
521 port->SignalPortComplete.connect(this, 553 port->SignalPortComplete.connect(this,
522 &BasicPortAllocatorSession::OnPortComplete); 554 &BasicPortAllocatorSession::OnPortComplete);
523 port->SignalDestroyed.connect(this, 555 port->SignalDestroyed.connect(this,
524 &BasicPortAllocatorSession::OnPortDestroyed); 556 &BasicPortAllocatorSession::OnPortDestroyed);
525 port->SignalPortError.connect( 557 port->SignalPortError.connect(
(...skipping 15 matching lines...) Expand all
541 ASSERT(rtc::Thread::Current() == network_thread_); 573 ASSERT(rtc::Thread::Current() == network_thread_);
542 PortData* data = FindPort(port); 574 PortData* data = FindPort(port);
543 ASSERT(data != NULL); 575 ASSERT(data != NULL);
544 // Discarding any candidate signal if port allocation status is 576 // Discarding any candidate signal if port allocation status is
545 // already in completed state. 577 // already in completed state.
546 if (data->complete() || data->error()) { 578 if (data->complete() || data->error()) {
547 return; 579 return;
548 } 580 }
549 581
550 ProtocolType pvalue; 582 ProtocolType pvalue;
551 bool candidate_signalable = CheckCandidateFilter(c);
552
553 // When device enumeration is disabled (to prevent non-default IP addresses
554 // from leaking), we ping from some local candidates even though we don't
555 // signal them. However, if host candidates are also disabled (for example, to
556 // prevent even default IP addresses from leaking), we still don't want to
557 // ping from them, even if device enumeration is disabled. Thus, we check for
558 // both device enumeration and host candidates being disabled.
559 bool network_enumeration_disabled = c.address().IsAnyIP();
560 bool can_ping_from_candidate =
561 (port->SharedSocket() || c.protocol() == TCP_PROTOCOL_NAME);
562 bool host_canidates_disabled = !(allocator_->candidate_filter() & CF_HOST);
563
564 bool candidate_pairable =
565 candidate_signalable ||
566 (network_enumeration_disabled && can_ping_from_candidate &&
567 !host_canidates_disabled);
568 bool candidate_protocol_enabled = 583 bool candidate_protocol_enabled =
569 StringToProto(c.protocol().c_str(), &pvalue) && 584 StringToProto(c.protocol().c_str(), &pvalue) &&
570 data->sequence()->ProtocolEnabled(pvalue); 585 data->sequence()->ProtocolEnabled(pvalue);
571 586
572 if (candidate_signalable && candidate_protocol_enabled) { 587 if (CheckCandidateFilter(c) && candidate_protocol_enabled) {
573 std::vector<Candidate> candidates; 588 std::vector<Candidate> candidates;
574 candidates.push_back(c); 589 candidates.push_back(SanitizeRelatedAddress(c));
575 SignalCandidatesReady(this, candidates); 590 SignalCandidatesReady(this, candidates);
576 } 591 }
577 592
578 // Port has been made ready. Nothing to do here. 593 // Port has been made ready. Nothing to do here.
579 if (data->ready()) { 594 if (data->ready()) {
580 return; 595 return;
581 } 596 }
582 597
583 // Move the port to the READY state, either because we have a usable candidate 598 // Move the port to the READY state, either because we have a usable candidate
584 // from the port, or simply because the port is bound to the any address and 599 // from the port, or simply because the port is bound to the any address and
585 // therefore has no host candidate. This will trigger the port to start 600 // therefore has no host candidate. This will trigger the port to start
586 // creating candidate pairs (connections) and issue connectivity checks. 601 // creating candidate pairs (connections) and issue connectivity checks.
587 if (candidate_pairable) { 602 if (CandidatePairable(c, port)) {
588 data->set_ready(); 603 data->set_ready(true);
589 SignalPortReady(this, port); 604 SignalPortReady(this, port);
590 } 605 }
591 } 606 }
592 607
593 void BasicPortAllocatorSession::OnPortComplete(Port* port) { 608 void BasicPortAllocatorSession::OnPortComplete(Port* port) {
594 ASSERT(rtc::Thread::Current() == network_thread_); 609 ASSERT(rtc::Thread::Current() == network_thread_);
595 PortData* data = FindPort(port); 610 PortData* data = FindPort(port);
596 ASSERT(data != NULL); 611 ASSERT(data != NULL);
597 612
598 // Ignore any late signals. 613 // Ignore any late signals.
(...skipping 26 matching lines...) Expand all
625 void BasicPortAllocatorSession::OnProtocolEnabled(AllocationSequence* seq, 640 void BasicPortAllocatorSession::OnProtocolEnabled(AllocationSequence* seq,
626 ProtocolType proto) { 641 ProtocolType proto) {
627 std::vector<Candidate> candidates; 642 std::vector<Candidate> candidates;
628 for (std::vector<PortData>::iterator it = ports_.begin(); 643 for (std::vector<PortData>::iterator it = ports_.begin();
629 it != ports_.end(); ++it) { 644 it != ports_.end(); ++it) {
630 if (it->sequence() != seq) 645 if (it->sequence() != seq)
631 continue; 646 continue;
632 647
633 const std::vector<Candidate>& potentials = it->port()->Candidates(); 648 const std::vector<Candidate>& potentials = it->port()->Candidates();
634 for (size_t i = 0; i < potentials.size(); ++i) { 649 for (size_t i = 0; i < potentials.size(); ++i) {
635 if (!CheckCandidateFilter(potentials[i])) 650 if (!CheckCandidateFilter(potentials[i])) {
636 continue; 651 continue;
652 }
637 ProtocolType pvalue; 653 ProtocolType pvalue;
638 bool candidate_protocol_enabled = 654 bool candidate_protocol_enabled =
639 StringToProto(potentials[i].protocol().c_str(), &pvalue) && 655 StringToProto(potentials[i].protocol().c_str(), &pvalue) &&
640 pvalue == proto; 656 pvalue == proto;
641 if (candidate_protocol_enabled) { 657 if (candidate_protocol_enabled) {
642 candidates.push_back(potentials[i]); 658 candidates.push_back(potentials[i]);
643 } 659 }
644 } 660 }
645 } 661 }
646 662
647 if (!candidates.empty()) { 663 if (!candidates.empty()) {
648 SignalCandidatesReady(this, candidates); 664 SignalCandidatesReady(this, candidates);
649 } 665 }
650 } 666 }
651 667
652 bool BasicPortAllocatorSession::CheckCandidateFilter(const Candidate& c) const { 668 bool BasicPortAllocatorSession::CheckCandidateFilter(const Candidate& c) const {
653 uint32_t filter = allocator_->candidate_filter(); 669 uint32_t filter = candidate_filter_;
654 670
655 // When binding to any address, before sending packets out, the getsockname 671 // When binding to any address, before sending packets out, the getsockname
656 // returns all 0s, but after sending packets, it'll be the NIC used to 672 // returns all 0s, but after sending packets, it'll be the NIC used to
657 // send. All 0s is not a valid ICE candidate address and should be filtered 673 // send. All 0s is not a valid ICE candidate address and should be filtered
658 // out. 674 // out.
659 if (c.address().IsAnyIP()) { 675 if (c.address().IsAnyIP()) {
660 return false; 676 return false;
661 } 677 }
662 678
663 if (c.type() == RELAY_PORT_TYPE) { 679 if (c.type() == RELAY_PORT_TYPE) {
664 return ((filter & CF_RELAY) != 0); 680 return ((filter & CF_RELAY) != 0);
665 } else if (c.type() == STUN_PORT_TYPE) { 681 } else if (c.type() == STUN_PORT_TYPE) {
666 return ((filter & CF_REFLEXIVE) != 0); 682 return ((filter & CF_REFLEXIVE) != 0);
667 } else if (c.type() == LOCAL_PORT_TYPE) { 683 } else if (c.type() == LOCAL_PORT_TYPE) {
668 if ((filter & CF_REFLEXIVE) && !c.address().IsPrivateIP()) { 684 if ((filter & CF_REFLEXIVE) && !c.address().IsPrivateIP()) {
669 // We allow host candidates if the filter allows server-reflexive 685 // We allow host candidates if the filter allows server-reflexive
670 // candidates and the candidate is a public IP. Because we don't generate 686 // candidates and the candidate is a public IP. Because we don't generate
671 // server-reflexive candidates if they have the same IP as the host 687 // server-reflexive candidates if they have the same IP as the host
672 // candidate (i.e. when the host candidate is a public IP), filtering to 688 // candidate (i.e. when the host candidate is a public IP), filtering to
673 // only server-reflexive candidates won't work right when the host 689 // only server-reflexive candidates won't work right when the host
674 // candidates have public IPs. 690 // candidates have public IPs.
675 return true; 691 return true;
676 } 692 }
677 693
678 return ((filter & CF_HOST) != 0); 694 return ((filter & CF_HOST) != 0);
679 } 695 }
680 return false; 696 return false;
681 } 697 }
682 698
699 bool BasicPortAllocatorSession::CandidatePairable(const Candidate& c,
700 const Port* port) const {
701 bool candidate_signalable = CheckCandidateFilter(c);
702
703 // When device enumeration is disabled (to prevent non-default IP addresses
704 // from leaking), we ping from some local candidates even though we don't
705 // signal them. However, if host candidates are also disabled (for example, to
706 // prevent even default IP addresses from leaking), we still don't want to
707 // ping from them, even if device enumeration is disabled. Thus, we check for
708 // both device enumeration and host candidates being disabled.
709 bool network_enumeration_disabled = c.address().IsAnyIP();
710 bool can_ping_from_candidate =
711 (port->SharedSocket() || c.protocol() == TCP_PROTOCOL_NAME);
712 bool host_candidates_disabled = !(candidate_filter_ & CF_HOST);
713
714 return candidate_signalable ||
715 (network_enumeration_disabled && can_ping_from_candidate &&
716 !host_candidates_disabled);
717 }
718
683 void BasicPortAllocatorSession::OnPortAllocationComplete( 719 void BasicPortAllocatorSession::OnPortAllocationComplete(
684 AllocationSequence* seq) { 720 AllocationSequence* seq) {
685 // Send candidate allocation complete signal if all ports are done. 721 // Send candidate allocation complete signal if all ports are done.
686 MaybeSignalCandidatesAllocationDone(); 722 MaybeSignalCandidatesAllocationDone();
687 } 723 }
688 724
689 void BasicPortAllocatorSession::MaybeSignalCandidatesAllocationDone() { 725 void BasicPortAllocatorSession::MaybeSignalCandidatesAllocationDone() {
690 if (CandidatesAllocationDone()) { 726 if (CandidatesAllocationDone()) {
691 if (pooled()) { 727 if (pooled()) {
692 LOG(LS_INFO) << "All candidates gathered for pooled session."; 728 LOG(LS_INFO) << "All candidates gathered for pooled session.";
(...skipping 13 matching lines...) Expand all
706 if (port == iter->port()) { 742 if (port == iter->port()) {
707 ports_.erase(iter); 743 ports_.erase(iter);
708 LOG_J(LS_INFO, port) << "Removed port from allocator (" 744 LOG_J(LS_INFO, port) << "Removed port from allocator ("
709 << static_cast<int>(ports_.size()) << " remaining)"; 745 << static_cast<int>(ports_.size()) << " remaining)";
710 return; 746 return;
711 } 747 }
712 } 748 }
713 ASSERT(false); 749 ASSERT(false);
714 } 750 }
715 751
716 void BasicPortAllocatorSession::OnShake() { 752 void BasicPortAllocatorSession::OnShake() {
Taylor Brandstetter 2016/05/19 22:11:45 Will remove this in a later CL.
717 LOG(INFO) << ">>>>> SHAKE <<<<< >>>>> SHAKE <<<<< >>>>> SHAKE <<<<<"; 753 LOG(INFO) << ">>>>> SHAKE <<<<< >>>>> SHAKE <<<<< >>>>> SHAKE <<<<<";
718 754
719 std::vector<Port*> ports; 755 std::vector<Port*> ports;
720 std::vector<Connection*> connections; 756 std::vector<Connection*> connections;
721 757
722 for (size_t i = 0; i < ports_.size(); ++i) { 758 for (size_t i = 0; i < ports_.size(); ++i) {
723 if (ports_[i].ready()) 759 if (ports_[i].ready() && !ports_[i].complete() && !ports_[i].error()) {
724 ports.push_back(ports_[i].port()); 760 ports.push_back(ports_[i].port());
761 }
725 } 762 }
726 763
727 for (size_t i = 0; i < ports.size(); ++i) { 764 for (size_t i = 0; i < ports.size(); ++i) {
728 Port::AddressMap::const_iterator iter; 765 Port::AddressMap::const_iterator iter;
729 for (iter = ports[i]->connections().begin(); 766 for (iter = ports[i]->connections().begin();
730 iter != ports[i]->connections().end(); 767 iter != ports[i]->connections().end();
731 ++iter) { 768 ++iter) {
732 connections.push_back(iter->second); 769 connections.push_back(iter->second);
733 } 770 }
734 } 771 }
(...skipping 498 matching lines...) Expand 10 before | Expand all | Expand 10 after
1233 ServerAddresses servers; 1270 ServerAddresses servers;
1234 for (size_t i = 0; i < relays.size(); ++i) { 1271 for (size_t i = 0; i < relays.size(); ++i) {
1235 if (relays[i].type == turn_type && SupportsProtocol(relays[i], type)) { 1272 if (relays[i].type == turn_type && SupportsProtocol(relays[i], type)) {
1236 servers.insert(relays[i].ports.front().address); 1273 servers.insert(relays[i].ports.front().address);
1237 } 1274 }
1238 } 1275 }
1239 return servers; 1276 return servers;
1240 } 1277 }
1241 1278
1242 } // namespace cricket 1279 } // namespace cricket
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698