OLD | NEW |
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 Loading... |
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 Loading... |
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 Loading... |
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 Loading... |
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 Loading... |
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 Loading... |
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 |
OLD | NEW |