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

Side by Side Diff: webrtc/p2p/base/p2ptransportchannel.cc

Issue 1498993002: Add ufrag to the ICE candidate signaling. (Closed) Base URL: https://chromium.googlesource.com/external/webrtc@master
Patch Set: Created 5 years 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
« no previous file with comments | « webrtc/p2p/base/p2ptransportchannel.h ('k') | webrtc/p2p/base/p2ptransportchannel_unittest.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
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 200 matching lines...) Expand 10 before | Expand all | Expand 10 after
211 allocator_(allocator), 211 allocator_(allocator),
212 worker_thread_(rtc::Thread::Current()), 212 worker_thread_(rtc::Thread::Current()),
213 incoming_only_(false), 213 incoming_only_(false),
214 error_(0), 214 error_(0),
215 best_connection_(NULL), 215 best_connection_(NULL),
216 pending_best_connection_(NULL), 216 pending_best_connection_(NULL),
217 sort_dirty_(false), 217 sort_dirty_(false),
218 remote_ice_mode_(ICEMODE_FULL), 218 remote_ice_mode_(ICEMODE_FULL),
219 ice_role_(ICEROLE_UNKNOWN), 219 ice_role_(ICEROLE_UNKNOWN),
220 tiebreaker_(0), 220 tiebreaker_(0),
221 remote_candidate_generation_(0),
222 gathering_state_(kIceGatheringNew), 221 gathering_state_(kIceGatheringNew),
223 check_receiving_delay_(MIN_CHECK_RECEIVING_DELAY * 5), 222 check_receiving_delay_(MIN_CHECK_RECEIVING_DELAY * 5),
224 receiving_timeout_(MIN_CHECK_RECEIVING_DELAY * 50), 223 receiving_timeout_(MIN_CHECK_RECEIVING_DELAY * 50),
225 backup_connection_ping_interval_(0) { 224 backup_connection_ping_interval_(0) {
226 uint32_t weak_ping_delay = ::strtoul( 225 uint32_t weak_ping_delay = ::strtoul(
227 webrtc::field_trial::FindFullName("WebRTC-StunInterPacketDelay").c_str(), 226 webrtc::field_trial::FindFullName("WebRTC-StunInterPacketDelay").c_str(),
228 nullptr, 10); 227 nullptr, 10);
229 if (weak_ping_delay) { 228 if (weak_ping_delay) {
230 weak_ping_delay_ = weak_ping_delay; 229 weak_ping_delay_ = weak_ping_delay;
231 } 230 }
(...skipping 108 matching lines...) Expand 10 before | Expand all | Expand 10 after
340 ASSERT(worker_thread_ == rtc::Thread::Current()); 339 ASSERT(worker_thread_ == rtc::Thread::Current());
341 ice_ufrag_ = ice_ufrag; 340 ice_ufrag_ = ice_ufrag;
342 ice_pwd_ = ice_pwd; 341 ice_pwd_ = ice_pwd;
343 // Note: Candidate gathering will restart when MaybeStartGathering is next 342 // Note: Candidate gathering will restart when MaybeStartGathering is next
344 // called. 343 // called.
345 } 344 }
346 345
347 void P2PTransportChannel::SetRemoteIceCredentials(const std::string& ice_ufrag, 346 void P2PTransportChannel::SetRemoteIceCredentials(const std::string& ice_ufrag,
348 const std::string& ice_pwd) { 347 const std::string& ice_pwd) {
349 ASSERT(worker_thread_ == rtc::Thread::Current()); 348 ASSERT(worker_thread_ == rtc::Thread::Current());
350 bool ice_restart = false; 349 IceParameters* current_ice = remote_ice();
351 if (!remote_ice_ufrag_.empty() && !remote_ice_pwd_.empty()) { 350 IceParameters new_ice(ice_ufrag, ice_pwd);
352 ice_restart = (remote_ice_ufrag_ != ice_ufrag) || 351 if (!current_ice || *current_ice != new_ice) {
353 (remote_ice_pwd_!= ice_pwd); 352 // Keep the ICE credentials so that newer connections
353 // are prioritized over the older ones.
354 remote_ice_parameters_.push_back(new_ice);
354 } 355 }
355 356
356 remote_ice_ufrag_ = ice_ufrag;
357 remote_ice_pwd_ = ice_pwd;
358
359 // We need to update the credentials for any peer reflexive candidates. 357 // We need to update the credentials for any peer reflexive candidates.
360 std::vector<Connection*>::iterator it = connections_.begin(); 358 std::vector<Connection*>::iterator it = connections_.begin();
361 for (; it != connections_.end(); ++it) { 359 for (; it != connections_.end(); ++it) {
362 (*it)->MaybeSetRemoteIceCredentials(ice_ufrag, ice_pwd); 360 (*it)->MaybeSetRemoteIceCredentials(ice_ufrag, ice_pwd);
363 } 361 }
364
365 if (ice_restart) {
366 // We need to keep track of the remote ice restart so newer
367 // connections are prioritized over the older.
368 ++remote_candidate_generation_;
369 }
370 } 362 }
371 363
372 void P2PTransportChannel::SetRemoteIceMode(IceMode mode) { 364 void P2PTransportChannel::SetRemoteIceMode(IceMode mode) {
373 remote_ice_mode_ = mode; 365 remote_ice_mode_ = mode;
374 } 366 }
375 367
376 void P2PTransportChannel::SetIceConfig(const IceConfig& config) { 368 void P2PTransportChannel::SetIceConfig(const IceConfig& config) {
377 gather_continually_ = config.gather_continually; 369 gather_continually_ = config.gather_continually;
378 LOG(LS_INFO) << "Set gather_continually to " << gather_continually_; 370 LOG(LS_INFO) << "Set gather_continually to " << gather_continually_;
379 371
(...skipping 149 matching lines...) Expand 10 before | Expand all | Expand 10 after
529 break; 521 break;
530 } 522 }
531 // We don't want to break here because we may find a match of the address 523 // We don't want to break here because we may find a match of the address
532 // later. 524 // later.
533 } 525 }
534 } 526 }
535 527
536 // The STUN binding request may arrive after setRemoteDescription and before 528 // The STUN binding request may arrive after setRemoteDescription and before
537 // adding remote candidate, so we need to set the password to the shared 529 // adding remote candidate, so we need to set the password to the shared
538 // password if the user name matches. 530 // password if the user name matches.
539 if (remote_password.empty() && remote_username == remote_ice_ufrag_) { 531 if (remote_password.empty()) {
540 remote_password = remote_ice_pwd_; 532 IceParameters* current_ice = remote_ice();
533 if (current_ice && remote_username == current_ice->ufrag) {
534 remote_password = current_ice->pwd;
535 }
541 } 536 }
542 537
543 Candidate remote_candidate; 538 Candidate remote_candidate;
544 bool remote_candidate_is_new = (candidate == nullptr); 539 bool remote_candidate_is_new = (candidate == nullptr);
545 if (!remote_candidate_is_new) { 540 if (!remote_candidate_is_new) {
546 remote_candidate = *candidate; 541 remote_candidate = *candidate;
547 if (ufrag_per_port) { 542 if (ufrag_per_port) {
548 remote_candidate.set_address(address); 543 remote_candidate.set_address(address);
549 } 544 }
550 } else { 545 } else {
(...skipping 97 matching lines...) Expand 10 before | Expand all | Expand 10 after
648 } else { 643 } else {
649 LOG(LS_INFO) << "Not switching the best connection on controlled side yet," 644 LOG(LS_INFO) << "Not switching the best connection on controlled side yet,"
650 << " because it's not writable: " << conn->ToString(); 645 << " because it's not writable: " << conn->ToString();
651 pending_best_connection_ = conn; 646 pending_best_connection_ = conn;
652 } 647 }
653 } 648 }
654 649
655 void P2PTransportChannel::AddRemoteCandidate(const Candidate& candidate) { 650 void P2PTransportChannel::AddRemoteCandidate(const Candidate& candidate) {
656 ASSERT(worker_thread_ == rtc::Thread::Current()); 651 ASSERT(worker_thread_ == rtc::Thread::Current());
657 652
658 uint32_t generation = candidate.generation(); 653 uint32_t generation = GetRemoteCandidateGeneration(candidate);
659 // Network may not guarantee the order of the candidate delivery. If a 654 // If a remote candidate with a previous generation arrives, drop it.
660 // remote candidate with an older generation arrives, drop it. 655 if (generation < remote_ice_generation()) {
661 if (generation != 0 && generation < remote_candidate_generation_) { 656 LOG(LS_WARNING) << "Dropping a remote candidate because its ufrag "
662 LOG(LS_WARNING) << "Dropping a remote candidate because its generation " 657 << candidate.username()
663 << generation 658 << " indicates it was for a previous generation.";
664 << " is lower than the current remote generation "
665 << remote_candidate_generation_;
666 return; 659 return;
667 } 660 }
668 661
662 Candidate new_remote_candidate(candidate);
663 new_remote_candidate.set_generation(generation);
664 // ICE candidates don't need to have username and password set, but
665 // the code below this (specifically, ConnectionRequest::Prepare in
666 // port.cc) uses the remote candidates's username. So, we set it
667 // here.
668 if (remote_ice()) {
669 if (candidate.username().empty()) {
670 new_remote_candidate.set_username(remote_ice()->ufrag);
671 }
672 if (new_remote_candidate.username() == remote_ice()->ufrag) {
673 if (candidate.password().empty()) {
674 new_remote_candidate.set_password(remote_ice()->pwd);
675 }
676 } else {
677 // The candidate belongs to the next generation. Its pwd will be set
678 // when the new remote ICE credentials arrive.
679 LOG(LS_WARNING) << "A remote candidate arrives with an unknown ufrag: "
680 << candidate.username();
681 }
682 }
683
669 // Create connections to this remote candidate. 684 // Create connections to this remote candidate.
670 CreateConnections(candidate, NULL); 685 CreateConnections(new_remote_candidate, NULL);
671 686
672 // Resort the connections list, which may have new elements. 687 // Resort the connections list, which may have new elements.
673 SortConnections(); 688 SortConnections();
674 } 689 }
675 690
676 // Creates connections from all of the ports that we care about to the given 691 // Creates connections from all of the ports that we care about to the given
677 // remote candidate. The return value is true if we created a connection from 692 // remote candidate. The return value is true if we created a connection from
678 // the origin port. 693 // the origin port.
679 bool P2PTransportChannel::CreateConnections(const Candidate& remote_candidate, 694 bool P2PTransportChannel::CreateConnections(const Candidate& remote_candidate,
680 PortInterface* origin_port) { 695 PortInterface* origin_port) {
681 ASSERT(worker_thread_ == rtc::Thread::Current()); 696 ASSERT(worker_thread_ == rtc::Thread::Current());
682 697
683 Candidate new_remote_candidate(remote_candidate);
684 new_remote_candidate.set_generation(
685 GetRemoteCandidateGeneration(remote_candidate));
686 // ICE candidates don't need to have username and password set, but
687 // the code below this (specifically, ConnectionRequest::Prepare in
688 // port.cc) uses the remote candidates's username. So, we set it
689 // here.
690 if (remote_candidate.username().empty()) {
691 new_remote_candidate.set_username(remote_ice_ufrag_);
692 }
693 if (remote_candidate.password().empty()) {
694 new_remote_candidate.set_password(remote_ice_pwd_);
695 }
696
697 // If we've already seen the new remote candidate (in the current candidate 698 // If we've already seen the new remote candidate (in the current candidate
698 // generation), then we shouldn't try creating connections for it. 699 // generation), then we shouldn't try creating connections for it.
699 // We either already have a connection for it, or we previously created one 700 // We either already have a connection for it, or we previously created one
700 // and then later pruned it. If we don't return, the channel will again 701 // and then later pruned it. If we don't return, the channel will again
701 // re-create any connections that were previously pruned, which will then 702 // re-create any connections that were previously pruned, which will then
702 // immediately be re-pruned, churning the network for no purpose. 703 // immediately be re-pruned, churning the network for no purpose.
703 // This only applies to candidates received over signaling (i.e. origin_port 704 // This only applies to candidates received over signaling (i.e. origin_port
704 // is NULL). 705 // is NULL).
705 if (!origin_port && IsDuplicateRemoteCandidate(new_remote_candidate)) { 706 if (!origin_port && IsDuplicateRemoteCandidate(remote_candidate)) {
706 // return true to indicate success, without creating any new connections. 707 // return true to indicate success, without creating any new connections.
707 return true; 708 return true;
708 } 709 }
709 710
710 // Add a new connection for this candidate to every port that allows such a 711 // Add a new connection for this candidate to every port that allows such a
711 // connection (i.e., if they have compatible protocols) and that does not 712 // connection (i.e., if they have compatible protocols) and that does not
712 // already have a connection to an equivalent candidate. We must be careful 713 // already have a connection to an equivalent candidate. We must be careful
713 // to make sure that the origin port is included, even if it was pruned, 714 // to make sure that the origin port is included, even if it was pruned,
714 // since that may be the only port that can create this connection. 715 // since that may be the only port that can create this connection.
715 bool created = false; 716 bool created = false;
716 std::vector<PortInterface *>::reverse_iterator it; 717 std::vector<PortInterface *>::reverse_iterator it;
717 for (it = ports_.rbegin(); it != ports_.rend(); ++it) { 718 for (it = ports_.rbegin(); it != ports_.rend(); ++it) {
718 if (CreateConnection(*it, new_remote_candidate, origin_port)) { 719 if (CreateConnection(*it, remote_candidate, origin_port)) {
719 if (*it == origin_port) 720 if (*it == origin_port)
720 created = true; 721 created = true;
721 } 722 }
722 } 723 }
723 724
724 if ((origin_port != NULL) && 725 if ((origin_port != NULL) &&
725 std::find(ports_.begin(), ports_.end(), origin_port) == ports_.end()) { 726 std::find(ports_.begin(), ports_.end(), origin_port) == ports_.end()) {
726 if (CreateConnection(origin_port, new_remote_candidate, origin_port)) 727 if (CreateConnection(origin_port, remote_candidate, origin_port))
727 created = true; 728 created = true;
728 } 729 }
729 730
730 // Remember this remote candidate so that we can add it to future ports. 731 // Remember this remote candidate so that we can add it to future ports.
731 RememberRemoteCandidate(new_remote_candidate, origin_port); 732 RememberRemoteCandidate(remote_candidate, origin_port);
732 733
733 return created; 734 return created;
734 } 735 }
735 736
736 // Setup a connection object for the local and remote candidate combination. 737 // Setup a connection object for the local and remote candidate combination.
737 // And then listen to connection object for changes. 738 // And then listen to connection object for changes.
738 bool P2PTransportChannel::CreateConnection(PortInterface* port, 739 bool P2PTransportChannel::CreateConnection(PortInterface* port,
739 const Candidate& remote_candidate, 740 const Candidate& remote_candidate,
740 PortInterface* origin_port) { 741 PortInterface* origin_port) {
741 // Look for an existing connection with this remote address. If one is not 742 // Look for an existing connection with this remote address. If one is not
(...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after
779 cricket::Connection* connection) const { 780 cricket::Connection* connection) const {
780 std::vector<Connection*>::const_iterator citer = 781 std::vector<Connection*>::const_iterator citer =
781 std::find(connections_.begin(), connections_.end(), connection); 782 std::find(connections_.begin(), connections_.end(), connection);
782 return citer != connections_.end(); 783 return citer != connections_.end();
783 } 784 }
784 785
785 uint32_t P2PTransportChannel::GetRemoteCandidateGeneration( 786 uint32_t P2PTransportChannel::GetRemoteCandidateGeneration(
786 const Candidate& candidate) { 787 const Candidate& candidate) {
787 // We need to keep track of the remote ice restart so newer 788 // We need to keep track of the remote ice restart so newer
788 // connections are prioritized over the older. 789 // connections are prioritized over the older.
789 ASSERT(candidate.generation() == 0 || 790 const auto& params = remote_ice_parameters_;
790 candidate.generation() == remote_candidate_generation_); 791 if (!candidate.username().empty()) {
791 return remote_candidate_generation_; 792 // If remote side sets the ufrag, we use that to determine the candidate
793 // generation.
794 // Search backward as it is more likely to find it near the end.
795 auto it = std::find_if(params.rbegin(), params.rend(),
796 [candidate](const IceParameters& param) {
797 return param.ufrag == candidate.username();
798 });
799 if (it == params.rend()) {
800 // If not found, assume it is the next (future) generation.
801 return static_cast<uint32_t>(remote_ice_parameters_.size());
802 }
803 return params.rend() - it - 1;
804 }
805 // If candidate generation is set, use that.
806 if (candidate.generation() > 0) {
807 return candidate.generation();
808 }
809 // Otherwise, assume the generation from remote ice parameters.
810 return remote_ice_generation();
792 } 811 }
793 812
794 // Check if remote candidate is already cached. 813 // Check if remote candidate is already cached.
795 bool P2PTransportChannel::IsDuplicateRemoteCandidate( 814 bool P2PTransportChannel::IsDuplicateRemoteCandidate(
796 const Candidate& candidate) { 815 const Candidate& candidate) {
797 for (size_t i = 0; i < remote_candidates_.size(); ++i) { 816 for (size_t i = 0; i < remote_candidates_.size(); ++i) {
798 if (remote_candidates_[i].IsEquivalent(candidate)) { 817 if (remote_candidates_[i].IsEquivalent(candidate)) {
799 return true; 818 return true;
800 } 819 }
801 } 820 }
(...skipping 592 matching lines...) Expand 10 before | Expand all | Expand 10 after
1394 SignalSentPacket(this, sent_packet); 1413 SignalSentPacket(this, sent_packet);
1395 } 1414 }
1396 1415
1397 void P2PTransportChannel::OnReadyToSend(Connection* connection) { 1416 void P2PTransportChannel::OnReadyToSend(Connection* connection) {
1398 if (connection == best_connection_ && writable()) { 1417 if (connection == best_connection_ && writable()) {
1399 SignalReadyToSend(this); 1418 SignalReadyToSend(this);
1400 } 1419 }
1401 } 1420 }
1402 1421
1403 } // namespace cricket 1422 } // namespace cricket
OLDNEW
« no previous file with comments | « webrtc/p2p/base/p2ptransportchannel.h ('k') | webrtc/p2p/base/p2ptransportchannel_unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698