| 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 |