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

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: Undoing unintentional "git cl format" of unrelated files. 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 149 matching lines...) Expand 10 before | Expand all | Expand 10 after
160 for (it = ports_.begin(); it != ports_.end(); it++) 160 for (it = ports_.begin(); it != ports_.end(); it++)
161 delete it->port(); 161 delete it->port();
162 162
163 for (uint32_t i = 0; i < configs_.size(); ++i) 163 for (uint32_t i = 0; i < configs_.size(); ++i)
164 delete configs_[i]; 164 delete configs_[i];
165 165
166 for (uint32_t i = 0; i < sequences_.size(); ++i) 166 for (uint32_t i = 0; i < sequences_.size(); ++i)
167 delete sequences_[i]; 167 delete sequences_[i];
168 } 168 }
169 169
170 void BasicPortAllocatorSession::SetCandidateFilter(uint32_t filter) {
171 if (filter == candidate_filter_) {
172 return;
173 }
174 // We assume the filter will only change from "ALL" to something else.
175 RTC_DCHECK(candidate_filter_ == CF_ALL);
176 candidate_filter_ = filter;
177 for (PortData& port : ports_) {
178 if (!port.has_pairable_candidate()) {
179 continue;
180 }
181 const auto& candidates = port.port()->Candidates();
182 // Setting a filter may cause a ready port to become non-ready
183 // if it no longer has any pairable candidates.
184 if (!std::any_of(candidates.begin(), candidates.end(),
185 [this, &port](const Candidate& candidate) {
186 return CandidatePairable(candidate, port.port());
187 })) {
188 port.set_has_pairable_candidate(false);
189 }
190 }
191 }
192
170 void BasicPortAllocatorSession::StartGettingPorts() { 193 void BasicPortAllocatorSession::StartGettingPorts() {
171 network_thread_ = rtc::Thread::Current(); 194 network_thread_ = rtc::Thread::Current();
172 if (!socket_factory_) { 195 if (!socket_factory_) {
173 owned_socket_factory_.reset( 196 owned_socket_factory_.reset(
174 new rtc::BasicPacketSocketFactory(network_thread_)); 197 new rtc::BasicPacketSocketFactory(network_thread_));
175 socket_factory_ = owned_socket_factory_.get(); 198 socket_factory_ = owned_socket_factory_.get();
176 } 199 }
177 200
178 running_ = true; 201 running_ = true;
179 network_thread_->Post(this, MSG_CONFIG_START); 202 network_thread_->Post(this, MSG_CONFIG_START);
180 } 203 }
181 204
182 void BasicPortAllocatorSession::StopGettingPorts() { 205 void BasicPortAllocatorSession::StopGettingPorts() {
183 ASSERT(rtc::Thread::Current() == network_thread_); 206 ASSERT(rtc::Thread::Current() == network_thread_);
184 running_ = false; 207 running_ = false;
185 network_thread_->Post(this, MSG_CONFIG_STOP); 208 network_thread_->Post(this, MSG_CONFIG_STOP);
186 ClearGettingPorts(); 209 ClearGettingPorts();
187 } 210 }
188 211
189 void BasicPortAllocatorSession::ClearGettingPorts() { 212 void BasicPortAllocatorSession::ClearGettingPorts() {
190 network_thread_->Clear(this, MSG_ALLOCATE); 213 network_thread_->Clear(this, MSG_ALLOCATE);
191 for (uint32_t i = 0; i < sequences_.size(); ++i) 214 for (uint32_t i = 0; i < sequences_.size(); ++i)
192 sequences_[i]->Stop(); 215 sequences_[i]->Stop();
193 } 216 }
194 217
195 std::vector<PortInterface*> BasicPortAllocatorSession::ReadyPorts() const { 218 std::vector<PortInterface*> BasicPortAllocatorSession::ReadyPorts() const {
196 std::vector<PortInterface*> ret; 219 std::vector<PortInterface*> ret;
197 for (const PortData& port : ports_) { 220 for (const PortData& port : ports_) {
198 if (port.ready() || port.complete()) { 221 if (port.has_pairable_candidate() && !port.error()) {
199 ret.push_back(port.port()); 222 ret.push_back(port.port());
200 } 223 }
201 } 224 }
202 return ret; 225 return ret;
203 } 226 }
204 227
205 std::vector<Candidate> BasicPortAllocatorSession::ReadyCandidates() const { 228 std::vector<Candidate> BasicPortAllocatorSession::ReadyCandidates() const {
206 std::vector<Candidate> candidates; 229 std::vector<Candidate> candidates;
207 for (const PortData& data : ports_) { 230 for (const PortData& data : ports_) {
208 for (const Candidate& candidate : data.port()->Candidates()) { 231 for (const Candidate& candidate : data.port()->Candidates()) {
209 if (!CheckCandidateFilter(candidate)) { 232 if (!CheckCandidateFilter(candidate)) {
210 continue; 233 continue;
211 } 234 }
212 ProtocolType pvalue; 235 ProtocolType pvalue;
213 if (!StringToProto(candidate.protocol().c_str(), &pvalue) || 236 if (!StringToProto(candidate.protocol().c_str(), &pvalue) ||
214 !data.sequence()->ProtocolEnabled(pvalue)) { 237 !data.sequence()->ProtocolEnabled(pvalue)) {
215 continue; 238 continue;
216 } 239 }
217 candidates.push_back(candidate); 240 candidates.push_back(SanitizeRelatedAddress(candidate));
218 } 241 }
219 } 242 }
220 return candidates; 243 return candidates;
221 } 244 }
222 245
246 Candidate BasicPortAllocatorSession::SanitizeRelatedAddress(
247 const Candidate& c) const {
248 Candidate copy = c;
249 // If adapter enumeration is disabled or host candidates are disabled,
250 // clear the raddr of STUN candidates to avoid local address leakage.
251 bool filter_stun_related_address =
252 ((flags() & PORTALLOCATOR_DISABLE_ADAPTER_ENUMERATION) &&
253 (flags() & PORTALLOCATOR_DISABLE_DEFAULT_LOCAL_CANDIDATE)) ||
254 !(candidate_filter_ & CF_HOST);
255 // If the candidate filter doesn't allow reflexive addresses, empty TURN raddr
256 // to avoid reflexive address leakage.
257 bool filter_turn_related_address = !(candidate_filter_ & CF_REFLEXIVE);
258 if ((c.type() == STUN_PORT_TYPE && filter_stun_related_address) ||
259 (c.type() == RELAY_PORT_TYPE && filter_turn_related_address)) {
260 copy.set_related_address(
261 rtc::EmptySocketAddressWithFamily(copy.address().family()));
262 }
263 return copy;
264 }
265
223 bool BasicPortAllocatorSession::CandidatesAllocationDone() const { 266 bool BasicPortAllocatorSession::CandidatesAllocationDone() const {
224 // Done only if all required AllocationSequence objects 267 // Done only if all required AllocationSequence objects
225 // are created. 268 // are created.
226 if (!allocation_sequences_created_) { 269 if (!allocation_sequences_created_) {
227 return false; 270 return false;
228 } 271 }
229 272
230 // Check that all port allocation sequences are complete (not running). 273 // Check that all port allocation sequences are complete (not running).
231 if (std::any_of(sequences_.begin(), sequences_.end(), 274 if (std::any_of(sequences_.begin(), sequences_.end(),
232 [](const AllocationSequence* sequence) { 275 [](const AllocationSequence* sequence) {
(...skipping 243 matching lines...) Expand 10 before | Expand all | Expand 10 after
476 519
477 LOG(LS_INFO) << "Adding allocated port for " << content_name(); 520 LOG(LS_INFO) << "Adding allocated port for " << content_name();
478 port->set_content_name(content_name()); 521 port->set_content_name(content_name());
479 port->set_component(component()); 522 port->set_component(component());
480 port->set_generation(generation()); 523 port->set_generation(generation());
481 if (allocator_->proxy().type != rtc::PROXY_NONE) 524 if (allocator_->proxy().type != rtc::PROXY_NONE)
482 port->set_proxy(allocator_->user_agent(), allocator_->proxy()); 525 port->set_proxy(allocator_->user_agent(), allocator_->proxy());
483 port->set_send_retransmit_count_attribute( 526 port->set_send_retransmit_count_attribute(
484 (flags() & PORTALLOCATOR_ENABLE_STUN_RETRANSMIT_ATTRIBUTE) != 0); 527 (flags() & PORTALLOCATOR_ENABLE_STUN_RETRANSMIT_ATTRIBUTE) != 0);
485 528
486 // Push down the candidate_filter to individual port.
487 uint32_t candidate_filter = allocator_->candidate_filter();
488
489 // When adapter enumeration is disabled, disable CF_HOST at port level so
490 // local address is not leaked by stunport in the candidate's related address.
491 if ((flags() & PORTALLOCATOR_DISABLE_ADAPTER_ENUMERATION) &&
492 (flags() & PORTALLOCATOR_DISABLE_DEFAULT_LOCAL_CANDIDATE)) {
493 candidate_filter &= ~CF_HOST;
494 }
495 port->set_candidate_filter(candidate_filter);
496
497 PortData data(port, seq); 529 PortData data(port, seq);
498 ports_.push_back(data); 530 ports_.push_back(data);
499 531
500 port->SignalCandidateReady.connect( 532 port->SignalCandidateReady.connect(
501 this, &BasicPortAllocatorSession::OnCandidateReady); 533 this, &BasicPortAllocatorSession::OnCandidateReady);
502 port->SignalPortComplete.connect(this, 534 port->SignalPortComplete.connect(this,
503 &BasicPortAllocatorSession::OnPortComplete); 535 &BasicPortAllocatorSession::OnPortComplete);
504 port->SignalDestroyed.connect(this, 536 port->SignalDestroyed.connect(this,
505 &BasicPortAllocatorSession::OnPortDestroyed); 537 &BasicPortAllocatorSession::OnPortDestroyed);
506 port->SignalPortError.connect( 538 port->SignalPortError.connect(
(...skipping 15 matching lines...) Expand all
522 ASSERT(rtc::Thread::Current() == network_thread_); 554 ASSERT(rtc::Thread::Current() == network_thread_);
523 PortData* data = FindPort(port); 555 PortData* data = FindPort(port);
524 ASSERT(data != NULL); 556 ASSERT(data != NULL);
525 // Discarding any candidate signal if port allocation status is 557 // Discarding any candidate signal if port allocation status is
526 // already in completed state. 558 // already in completed state.
527 if (data->complete() || data->error()) { 559 if (data->complete() || data->error()) {
528 return; 560 return;
529 } 561 }
530 562
531 ProtocolType pvalue; 563 ProtocolType pvalue;
532 bool candidate_signalable = CheckCandidateFilter(c);
533
534 // When device enumeration is disabled (to prevent non-default IP addresses
535 // from leaking), we ping from some local candidates even though we don't
536 // signal them. However, if host candidates are also disabled (for example, to
537 // prevent even default IP addresses from leaking), we still don't want to
538 // ping from them, even if device enumeration is disabled. Thus, we check for
539 // both device enumeration and host candidates being disabled.
540 bool network_enumeration_disabled = c.address().IsAnyIP();
541 bool can_ping_from_candidate =
542 (port->SharedSocket() || c.protocol() == TCP_PROTOCOL_NAME);
543 bool host_canidates_disabled = !(allocator_->candidate_filter() & CF_HOST);
544
545 bool candidate_pairable =
546 candidate_signalable ||
547 (network_enumeration_disabled && can_ping_from_candidate &&
548 !host_canidates_disabled);
549 bool candidate_protocol_enabled = 564 bool candidate_protocol_enabled =
550 StringToProto(c.protocol().c_str(), &pvalue) && 565 StringToProto(c.protocol().c_str(), &pvalue) &&
551 data->sequence()->ProtocolEnabled(pvalue); 566 data->sequence()->ProtocolEnabled(pvalue);
552 567
553 if (candidate_signalable && candidate_protocol_enabled) { 568 if (CheckCandidateFilter(c) && candidate_protocol_enabled) {
554 std::vector<Candidate> candidates; 569 std::vector<Candidate> candidates;
555 candidates.push_back(c); 570 candidates.push_back(SanitizeRelatedAddress(c));
556 SignalCandidatesReady(this, candidates); 571 SignalCandidatesReady(this, candidates);
557 } 572 }
558 573
559 // Port has been made ready. Nothing to do here. 574 // Port has already been marked as having a pairable candidate.
560 if (data->ready()) { 575 // Nothing to do here.
576 if (data->has_pairable_candidate()) {
561 return; 577 return;
562 } 578 }
563 579
564 // Move the port to the READY state, either because we have a usable candidate 580 // Mark that the port has a pairable candidate, either because we have a
565 // from the port, or simply because the port is bound to the any address and 581 // usable candidate from the port, or simply because the port is bound to the
566 // therefore has no host candidate. This will trigger the port to start 582 // any address and therefore has no host candidate. This will trigger the port
567 // creating candidate pairs (connections) and issue connectivity checks. 583 // to start creating candidate pairs (connections) and issue connectivity
568 if (candidate_pairable) { 584 // checks.
569 data->set_ready(); 585 if (CandidatePairable(c, port)) {
586 data->set_has_pairable_candidate(true);
570 SignalPortReady(this, port); 587 SignalPortReady(this, port);
571 } 588 }
572 } 589 }
573 590
574 void BasicPortAllocatorSession::OnPortComplete(Port* port) { 591 void BasicPortAllocatorSession::OnPortComplete(Port* port) {
575 ASSERT(rtc::Thread::Current() == network_thread_); 592 ASSERT(rtc::Thread::Current() == network_thread_);
576 PortData* data = FindPort(port); 593 PortData* data = FindPort(port);
577 ASSERT(data != NULL); 594 ASSERT(data != NULL);
578 595
579 // Ignore any late signals. 596 // Ignore any late signals.
(...skipping 26 matching lines...) Expand all
606 void BasicPortAllocatorSession::OnProtocolEnabled(AllocationSequence* seq, 623 void BasicPortAllocatorSession::OnProtocolEnabled(AllocationSequence* seq,
607 ProtocolType proto) { 624 ProtocolType proto) {
608 std::vector<Candidate> candidates; 625 std::vector<Candidate> candidates;
609 for (std::vector<PortData>::iterator it = ports_.begin(); 626 for (std::vector<PortData>::iterator it = ports_.begin();
610 it != ports_.end(); ++it) { 627 it != ports_.end(); ++it) {
611 if (it->sequence() != seq) 628 if (it->sequence() != seq)
612 continue; 629 continue;
613 630
614 const std::vector<Candidate>& potentials = it->port()->Candidates(); 631 const std::vector<Candidate>& potentials = it->port()->Candidates();
615 for (size_t i = 0; i < potentials.size(); ++i) { 632 for (size_t i = 0; i < potentials.size(); ++i) {
616 if (!CheckCandidateFilter(potentials[i])) 633 if (!CheckCandidateFilter(potentials[i])) {
617 continue; 634 continue;
635 }
618 ProtocolType pvalue; 636 ProtocolType pvalue;
619 bool candidate_protocol_enabled = 637 bool candidate_protocol_enabled =
620 StringToProto(potentials[i].protocol().c_str(), &pvalue) && 638 StringToProto(potentials[i].protocol().c_str(), &pvalue) &&
621 pvalue == proto; 639 pvalue == proto;
622 if (candidate_protocol_enabled) { 640 if (candidate_protocol_enabled) {
623 candidates.push_back(potentials[i]); 641 candidates.push_back(potentials[i]);
624 } 642 }
625 } 643 }
626 } 644 }
627 645
628 if (!candidates.empty()) { 646 if (!candidates.empty()) {
629 SignalCandidatesReady(this, candidates); 647 SignalCandidatesReady(this, candidates);
630 } 648 }
631 } 649 }
632 650
633 bool BasicPortAllocatorSession::CheckCandidateFilter(const Candidate& c) const { 651 bool BasicPortAllocatorSession::CheckCandidateFilter(const Candidate& c) const {
634 uint32_t filter = allocator_->candidate_filter(); 652 uint32_t filter = candidate_filter_;
635 653
636 // When binding to any address, before sending packets out, the getsockname 654 // When binding to any address, before sending packets out, the getsockname
637 // returns all 0s, but after sending packets, it'll be the NIC used to 655 // returns all 0s, but after sending packets, it'll be the NIC used to
638 // send. All 0s is not a valid ICE candidate address and should be filtered 656 // send. All 0s is not a valid ICE candidate address and should be filtered
639 // out. 657 // out.
640 if (c.address().IsAnyIP()) { 658 if (c.address().IsAnyIP()) {
641 return false; 659 return false;
642 } 660 }
643 661
644 if (c.type() == RELAY_PORT_TYPE) { 662 if (c.type() == RELAY_PORT_TYPE) {
645 return ((filter & CF_RELAY) != 0); 663 return ((filter & CF_RELAY) != 0);
646 } else if (c.type() == STUN_PORT_TYPE) { 664 } else if (c.type() == STUN_PORT_TYPE) {
647 return ((filter & CF_REFLEXIVE) != 0); 665 return ((filter & CF_REFLEXIVE) != 0);
648 } else if (c.type() == LOCAL_PORT_TYPE) { 666 } else if (c.type() == LOCAL_PORT_TYPE) {
649 if ((filter & CF_REFLEXIVE) && !c.address().IsPrivateIP()) { 667 if ((filter & CF_REFLEXIVE) && !c.address().IsPrivateIP()) {
650 // We allow host candidates if the filter allows server-reflexive 668 // We allow host candidates if the filter allows server-reflexive
651 // candidates and the candidate is a public IP. Because we don't generate 669 // candidates and the candidate is a public IP. Because we don't generate
652 // server-reflexive candidates if they have the same IP as the host 670 // server-reflexive candidates if they have the same IP as the host
653 // candidate (i.e. when the host candidate is a public IP), filtering to 671 // candidate (i.e. when the host candidate is a public IP), filtering to
654 // only server-reflexive candidates won't work right when the host 672 // only server-reflexive candidates won't work right when the host
655 // candidates have public IPs. 673 // candidates have public IPs.
656 return true; 674 return true;
657 } 675 }
658 676
659 return ((filter & CF_HOST) != 0); 677 return ((filter & CF_HOST) != 0);
660 } 678 }
661 return false; 679 return false;
662 } 680 }
663 681
682 bool BasicPortAllocatorSession::CandidatePairable(const Candidate& c,
683 const Port* port) const {
684 bool candidate_signalable = CheckCandidateFilter(c);
685
686 // When device enumeration is disabled (to prevent non-default IP addresses
687 // from leaking), we ping from some local candidates even though we don't
688 // signal them. However, if host candidates are also disabled (for example, to
689 // prevent even default IP addresses from leaking), we still don't want to
690 // ping from them, even if device enumeration is disabled. Thus, we check for
691 // both device enumeration and host candidates being disabled.
692 bool network_enumeration_disabled = c.address().IsAnyIP();
693 bool can_ping_from_candidate =
694 (port->SharedSocket() || c.protocol() == TCP_PROTOCOL_NAME);
695 bool host_candidates_disabled = !(candidate_filter_ & CF_HOST);
696
697 return candidate_signalable ||
698 (network_enumeration_disabled && can_ping_from_candidate &&
699 !host_candidates_disabled);
700 }
701
664 void BasicPortAllocatorSession::OnPortAllocationComplete( 702 void BasicPortAllocatorSession::OnPortAllocationComplete(
665 AllocationSequence* seq) { 703 AllocationSequence* seq) {
666 // Send candidate allocation complete signal if all ports are done. 704 // Send candidate allocation complete signal if all ports are done.
667 MaybeSignalCandidatesAllocationDone(); 705 MaybeSignalCandidatesAllocationDone();
668 } 706 }
669 707
670 void BasicPortAllocatorSession::MaybeSignalCandidatesAllocationDone() { 708 void BasicPortAllocatorSession::MaybeSignalCandidatesAllocationDone() {
671 if (CandidatesAllocationDone()) { 709 if (CandidatesAllocationDone()) {
672 if (pooled()) { 710 if (pooled()) {
673 LOG(LS_INFO) << "All candidates gathered for pooled session."; 711 LOG(LS_INFO) << "All candidates gathered for pooled session.";
(...skipping 510 matching lines...) Expand 10 before | Expand all | Expand 10 after
1184 ServerAddresses servers; 1222 ServerAddresses servers;
1185 for (size_t i = 0; i < relays.size(); ++i) { 1223 for (size_t i = 0; i < relays.size(); ++i) {
1186 if (relays[i].type == turn_type && SupportsProtocol(relays[i], type)) { 1224 if (relays[i].type == turn_type && SupportsProtocol(relays[i], type)) {
1187 servers.insert(relays[i].ports.front().address); 1225 servers.insert(relays[i].ports.front().address);
1188 } 1226 }
1189 } 1227 }
1190 return servers; 1228 return servers;
1191 } 1229 }
1192 1230
1193 } // namespace cricket 1231 } // namespace cricket
OLDNEW
« no previous file with comments | « webrtc/p2p/client/basicportallocator.h ('k') | webrtc/p2p/client/basicportallocator_unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698