| 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 111 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 122 RECEIVING_SWITCHING_DELAY) { | 122 RECEIVING_SWITCHING_DELAY) { |
| 123 uint32_t weak_ping_interval = ::strtoul( | 123 uint32_t weak_ping_interval = ::strtoul( |
| 124 webrtc::field_trial::FindFullName("WebRTC-StunInterPacketDelay").c_str(), | 124 webrtc::field_trial::FindFullName("WebRTC-StunInterPacketDelay").c_str(), |
| 125 nullptr, 10); | 125 nullptr, 10); |
| 126 if (weak_ping_interval) { | 126 if (weak_ping_interval) { |
| 127 weak_ping_interval_ = static_cast<int>(weak_ping_interval); | 127 weak_ping_interval_ = static_cast<int>(weak_ping_interval); |
| 128 } | 128 } |
| 129 } | 129 } |
| 130 | 130 |
| 131 P2PTransportChannel::~P2PTransportChannel() { | 131 P2PTransportChannel::~P2PTransportChannel() { |
| 132 ASSERT(network_thread_ == rtc::Thread::Current()); | 132 RTC_DCHECK(network_thread_ == rtc::Thread::Current()); |
| 133 } | 133 } |
| 134 | 134 |
| 135 // Add the allocator session to our list so that we know which sessions | 135 // Add the allocator session to our list so that we know which sessions |
| 136 // are still active. | 136 // are still active. |
| 137 void P2PTransportChannel::AddAllocatorSession( | 137 void P2PTransportChannel::AddAllocatorSession( |
| 138 std::unique_ptr<PortAllocatorSession> session) { | 138 std::unique_ptr<PortAllocatorSession> session) { |
| 139 ASSERT(network_thread_ == rtc::Thread::Current()); | 139 RTC_DCHECK(network_thread_ == rtc::Thread::Current()); |
| 140 | 140 |
| 141 session->set_generation(static_cast<uint32_t>(allocator_sessions_.size())); | 141 session->set_generation(static_cast<uint32_t>(allocator_sessions_.size())); |
| 142 session->SignalPortReady.connect(this, &P2PTransportChannel::OnPortReady); | 142 session->SignalPortReady.connect(this, &P2PTransportChannel::OnPortReady); |
| 143 session->SignalPortsPruned.connect(this, &P2PTransportChannel::OnPortsPruned); | 143 session->SignalPortsPruned.connect(this, &P2PTransportChannel::OnPortsPruned); |
| 144 session->SignalCandidatesReady.connect( | 144 session->SignalCandidatesReady.connect( |
| 145 this, &P2PTransportChannel::OnCandidatesReady); | 145 this, &P2PTransportChannel::OnCandidatesReady); |
| 146 session->SignalCandidatesRemoved.connect( | 146 session->SignalCandidatesRemoved.connect( |
| 147 this, &P2PTransportChannel::OnCandidatesRemoved); | 147 this, &P2PTransportChannel::OnCandidatesRemoved); |
| 148 session->SignalCandidatesAllocationDone.connect( | 148 session->SignalCandidatesAllocationDone.connect( |
| 149 this, &P2PTransportChannel::OnCandidatesAllocationDone); | 149 this, &P2PTransportChannel::OnCandidatesAllocationDone); |
| (...skipping 90 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 240 // threshold, the new connection is in a better receiving state than the | 240 // threshold, the new connection is in a better receiving state than the |
| 241 // currently selected connection. So we need to re-check whether it needs | 241 // currently selected connection. So we need to re-check whether it needs |
| 242 // to be switched at a later time. | 242 // to be switched at a later time. |
| 243 thread()->PostDelayed(RTC_FROM_HERE, *config_.receiving_switching_delay, | 243 thread()->PostDelayed(RTC_FROM_HERE, *config_.receiving_switching_delay, |
| 244 this, MSG_SORT_AND_UPDATE_STATE); | 244 this, MSG_SORT_AND_UPDATE_STATE); |
| 245 } | 245 } |
| 246 return false; | 246 return false; |
| 247 } | 247 } |
| 248 | 248 |
| 249 void P2PTransportChannel::SetIceRole(IceRole ice_role) { | 249 void P2PTransportChannel::SetIceRole(IceRole ice_role) { |
| 250 ASSERT(network_thread_ == rtc::Thread::Current()); | 250 RTC_DCHECK(network_thread_ == rtc::Thread::Current()); |
| 251 if (ice_role_ != ice_role) { | 251 if (ice_role_ != ice_role) { |
| 252 ice_role_ = ice_role; | 252 ice_role_ = ice_role; |
| 253 for (PortInterface* port : ports_) { | 253 for (PortInterface* port : ports_) { |
| 254 port->SetIceRole(ice_role); | 254 port->SetIceRole(ice_role); |
| 255 } | 255 } |
| 256 // Update role on pruned ports as well, because they may still have | 256 // Update role on pruned ports as well, because they may still have |
| 257 // connections alive that should be using the correct role. | 257 // connections alive that should be using the correct role. |
| 258 for (PortInterface* port : pruned_ports_) { | 258 for (PortInterface* port : pruned_ports_) { |
| 259 port->SetIceRole(ice_role); | 259 port->SetIceRole(ice_role); |
| 260 } | 260 } |
| 261 } | 261 } |
| 262 } | 262 } |
| 263 | 263 |
| 264 void P2PTransportChannel::SetIceTiebreaker(uint64_t tiebreaker) { | 264 void P2PTransportChannel::SetIceTiebreaker(uint64_t tiebreaker) { |
| 265 ASSERT(network_thread_ == rtc::Thread::Current()); | 265 RTC_DCHECK(network_thread_ == rtc::Thread::Current()); |
| 266 if (!ports_.empty() || !pruned_ports_.empty()) { | 266 if (!ports_.empty() || !pruned_ports_.empty()) { |
| 267 LOG(LS_ERROR) | 267 LOG(LS_ERROR) |
| 268 << "Attempt to change tiebreaker after Port has been allocated."; | 268 << "Attempt to change tiebreaker after Port has been allocated."; |
| 269 return; | 269 return; |
| 270 } | 270 } |
| 271 | 271 |
| 272 tiebreaker_ = tiebreaker; | 272 tiebreaker_ = tiebreaker; |
| 273 } | 273 } |
| 274 | 274 |
| 275 TransportChannelState P2PTransportChannel::GetState() const { | 275 TransportChannelState P2PTransportChannel::GetState() const { |
| (...skipping 27 matching lines...) Expand all Loading... |
| 303 << network->ToString() | 303 << network->ToString() |
| 304 << " has more than 1 connection."; | 304 << " has more than 1 connection."; |
| 305 return TransportChannelState::STATE_CONNECTING; | 305 return TransportChannelState::STATE_CONNECTING; |
| 306 } | 306 } |
| 307 } | 307 } |
| 308 | 308 |
| 309 return TransportChannelState::STATE_COMPLETED; | 309 return TransportChannelState::STATE_COMPLETED; |
| 310 } | 310 } |
| 311 | 311 |
| 312 void P2PTransportChannel::SetIceParameters(const IceParameters& ice_params) { | 312 void P2PTransportChannel::SetIceParameters(const IceParameters& ice_params) { |
| 313 ASSERT(network_thread_ == rtc::Thread::Current()); | 313 RTC_DCHECK(network_thread_ == rtc::Thread::Current()); |
| 314 LOG(LS_INFO) << "Set ICE ufrag: " << ice_params.ufrag | 314 LOG(LS_INFO) << "Set ICE ufrag: " << ice_params.ufrag |
| 315 << " pwd: " << ice_params.pwd << " on transport " | 315 << " pwd: " << ice_params.pwd << " on transport " |
| 316 << transport_name(); | 316 << transport_name(); |
| 317 ice_parameters_ = ice_params; | 317 ice_parameters_ = ice_params; |
| 318 // Note: Candidate gathering will restart when MaybeStartGathering is next | 318 // Note: Candidate gathering will restart when MaybeStartGathering is next |
| 319 // called. | 319 // called. |
| 320 } | 320 } |
| 321 | 321 |
| 322 void P2PTransportChannel::SetRemoteIceParameters( | 322 void P2PTransportChannel::SetRemoteIceParameters( |
| 323 const IceParameters& ice_params) { | 323 const IceParameters& ice_params) { |
| 324 ASSERT(network_thread_ == rtc::Thread::Current()); | 324 RTC_DCHECK(network_thread_ == rtc::Thread::Current()); |
| 325 LOG(LS_INFO) << "Remote supports ICE renomination ? " | 325 LOG(LS_INFO) << "Remote supports ICE renomination ? " |
| 326 << ice_params.renomination; | 326 << ice_params.renomination; |
| 327 IceParameters* current_ice = remote_ice(); | 327 IceParameters* current_ice = remote_ice(); |
| 328 if (!current_ice || *current_ice != ice_params) { | 328 if (!current_ice || *current_ice != ice_params) { |
| 329 // Keep the ICE credentials so that newer connections | 329 // Keep the ICE credentials so that newer connections |
| 330 // are prioritized over the older ones. | 330 // are prioritized over the older ones. |
| 331 remote_ice_parameters_.push_back(ice_params); | 331 remote_ice_parameters_.push_back(ice_params); |
| 332 } | 332 } |
| 333 | 333 |
| 334 // Update the pwd of remote candidate if needed. | 334 // Update the pwd of remote candidate if needed. |
| (...skipping 160 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 495 transport_name(), component(), ice_parameters_.ufrag, | 495 transport_name(), component(), ice_parameters_.ufrag, |
| 496 ice_parameters_.pwd)); | 496 ice_parameters_.pwd)); |
| 497 allocator_sessions_.back()->StartGettingPorts(); | 497 allocator_sessions_.back()->StartGettingPorts(); |
| 498 } | 498 } |
| 499 } | 499 } |
| 500 } | 500 } |
| 501 | 501 |
| 502 // A new port is available, attempt to make connections for it | 502 // A new port is available, attempt to make connections for it |
| 503 void P2PTransportChannel::OnPortReady(PortAllocatorSession *session, | 503 void P2PTransportChannel::OnPortReady(PortAllocatorSession *session, |
| 504 PortInterface* port) { | 504 PortInterface* port) { |
| 505 ASSERT(network_thread_ == rtc::Thread::Current()); | 505 RTC_DCHECK(network_thread_ == rtc::Thread::Current()); |
| 506 | 506 |
| 507 // Set in-effect options on the new port | 507 // Set in-effect options on the new port |
| 508 for (OptionMap::const_iterator it = options_.begin(); | 508 for (OptionMap::const_iterator it = options_.begin(); |
| 509 it != options_.end(); | 509 it != options_.end(); |
| 510 ++it) { | 510 ++it) { |
| 511 int val = port->SetOption(it->first, it->second); | 511 int val = port->SetOption(it->first, it->second); |
| 512 if (val < 0) { | 512 if (val < 0) { |
| 513 LOG_J(LS_WARNING, port) << "SetOption(" << it->first | 513 LOG_J(LS_WARNING, port) << "SetOption(" << it->first |
| 514 << ", " << it->second | 514 << ", " << it->second |
| 515 << ") failed: " << port->GetError(); | 515 << ") failed: " << port->GetError(); |
| (...skipping 24 matching lines...) Expand all Loading... |
| 540 CreateConnection(port, *iter, iter->origin_port()); | 540 CreateConnection(port, *iter, iter->origin_port()); |
| 541 } | 541 } |
| 542 | 542 |
| 543 SortConnectionsAndUpdateState(); | 543 SortConnectionsAndUpdateState(); |
| 544 } | 544 } |
| 545 | 545 |
| 546 // A new candidate is available, let listeners know | 546 // A new candidate is available, let listeners know |
| 547 void P2PTransportChannel::OnCandidatesReady( | 547 void P2PTransportChannel::OnCandidatesReady( |
| 548 PortAllocatorSession* session, | 548 PortAllocatorSession* session, |
| 549 const std::vector<Candidate>& candidates) { | 549 const std::vector<Candidate>& candidates) { |
| 550 ASSERT(network_thread_ == rtc::Thread::Current()); | 550 RTC_DCHECK(network_thread_ == rtc::Thread::Current()); |
| 551 for (size_t i = 0; i < candidates.size(); ++i) { | 551 for (size_t i = 0; i < candidates.size(); ++i) { |
| 552 SignalCandidateGathered(this, candidates[i]); | 552 SignalCandidateGathered(this, candidates[i]); |
| 553 } | 553 } |
| 554 } | 554 } |
| 555 | 555 |
| 556 void P2PTransportChannel::OnCandidatesAllocationDone( | 556 void P2PTransportChannel::OnCandidatesAllocationDone( |
| 557 PortAllocatorSession* session) { | 557 PortAllocatorSession* session) { |
| 558 ASSERT(network_thread_ == rtc::Thread::Current()); | 558 RTC_DCHECK(network_thread_ == rtc::Thread::Current()); |
| 559 if (config_.gather_continually()) { | 559 if (config_.gather_continually()) { |
| 560 LOG(LS_INFO) << "P2PTransportChannel: " << transport_name() | 560 LOG(LS_INFO) << "P2PTransportChannel: " << transport_name() |
| 561 << ", component " << component() | 561 << ", component " << component() |
| 562 << " gathering complete, but using continual " | 562 << " gathering complete, but using continual " |
| 563 << "gathering so not changing gathering state."; | 563 << "gathering so not changing gathering state."; |
| 564 return; | 564 return; |
| 565 } | 565 } |
| 566 gathering_state_ = kIceGatheringComplete; | 566 gathering_state_ = kIceGatheringComplete; |
| 567 LOG(LS_INFO) << "P2PTransportChannel: " << transport_name() << ", component " | 567 LOG(LS_INFO) << "P2PTransportChannel: " << transport_name() << ", component " |
| 568 << component() << " gathering complete"; | 568 << component() << " gathering complete"; |
| 569 SignalGatheringState(this); | 569 SignalGatheringState(this); |
| 570 } | 570 } |
| 571 | 571 |
| 572 // Handle stun packets | 572 // Handle stun packets |
| 573 void P2PTransportChannel::OnUnknownAddress( | 573 void P2PTransportChannel::OnUnknownAddress( |
| 574 PortInterface* port, | 574 PortInterface* port, |
| 575 const rtc::SocketAddress& address, ProtocolType proto, | 575 const rtc::SocketAddress& address, ProtocolType proto, |
| 576 IceMessage* stun_msg, const std::string &remote_username, | 576 IceMessage* stun_msg, const std::string &remote_username, |
| 577 bool port_muxed) { | 577 bool port_muxed) { |
| 578 ASSERT(network_thread_ == rtc::Thread::Current()); | 578 RTC_DCHECK(network_thread_ == rtc::Thread::Current()); |
| 579 | 579 |
| 580 // Port has received a valid stun packet from an address that no Connection | 580 // Port has received a valid stun packet from an address that no Connection |
| 581 // is currently available for. See if we already have a candidate with the | 581 // is currently available for. See if we already have a candidate with the |
| 582 // address. If it isn't we need to create new candidate for it. | 582 // address. If it isn't we need to create new candidate for it. |
| 583 | 583 |
| 584 const Candidate* candidate = nullptr; | 584 const Candidate* candidate = nullptr; |
| 585 for (const Candidate& c : remote_candidates_) { | 585 for (const Candidate& c : remote_candidates_) { |
| 586 if (c.username() == remote_username && c.address() == address && | 586 if (c.username() == remote_username && c.address() == address && |
| 587 c.protocol() == ProtoToString(proto)) { | 587 c.protocol() == ProtoToString(proto)) { |
| 588 candidate = &c; | 588 candidate = &c; |
| (...skipping 118 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 707 [ufrag](const IceParameters& param) { return param.ufrag == ufrag; }); | 707 [ufrag](const IceParameters& param) { return param.ufrag == ufrag; }); |
| 708 if (it == params.rend()) { | 708 if (it == params.rend()) { |
| 709 // Not found. | 709 // Not found. |
| 710 return nullptr; | 710 return nullptr; |
| 711 } | 711 } |
| 712 *generation = params.rend() - it - 1; | 712 *generation = params.rend() - it - 1; |
| 713 return &(*it); | 713 return &(*it); |
| 714 } | 714 } |
| 715 | 715 |
| 716 void P2PTransportChannel::OnNominated(Connection* conn) { | 716 void P2PTransportChannel::OnNominated(Connection* conn) { |
| 717 ASSERT(network_thread_ == rtc::Thread::Current()); | 717 RTC_DCHECK(network_thread_ == rtc::Thread::Current()); |
| 718 ASSERT(ice_role_ == ICEROLE_CONTROLLED); | 718 RTC_DCHECK(ice_role_ == ICEROLE_CONTROLLED); |
| 719 | 719 |
| 720 if (selected_connection_ == conn) { | 720 if (selected_connection_ == conn) { |
| 721 return; | 721 return; |
| 722 } | 722 } |
| 723 | 723 |
| 724 if (MaybeSwitchSelectedConnection(conn, | 724 if (MaybeSwitchSelectedConnection(conn, |
| 725 "nomination on the controlled side")) { | 725 "nomination on the controlled side")) { |
| 726 // Now that we have selected a connection, it is time to prune other | 726 // Now that we have selected a connection, it is time to prune other |
| 727 // connections and update the read/write state of the channel. | 727 // connections and update the read/write state of the channel. |
| 728 RequestSortAndStateUpdate(); | 728 RequestSortAndStateUpdate(); |
| 729 } else { | 729 } else { |
| 730 LOG(LS_INFO) | 730 LOG(LS_INFO) |
| 731 << "Not switching the selected connection on controlled side yet: " | 731 << "Not switching the selected connection on controlled side yet: " |
| 732 << conn->ToString(); | 732 << conn->ToString(); |
| 733 } | 733 } |
| 734 } | 734 } |
| 735 | 735 |
| 736 void P2PTransportChannel::AddRemoteCandidate(const Candidate& candidate) { | 736 void P2PTransportChannel::AddRemoteCandidate(const Candidate& candidate) { |
| 737 ASSERT(network_thread_ == rtc::Thread::Current()); | 737 RTC_DCHECK(network_thread_ == rtc::Thread::Current()); |
| 738 | 738 |
| 739 uint32_t generation = GetRemoteCandidateGeneration(candidate); | 739 uint32_t generation = GetRemoteCandidateGeneration(candidate); |
| 740 // If a remote candidate with a previous generation arrives, drop it. | 740 // If a remote candidate with a previous generation arrives, drop it. |
| 741 if (generation < remote_ice_generation()) { | 741 if (generation < remote_ice_generation()) { |
| 742 LOG(LS_WARNING) << "Dropping a remote candidate because its ufrag " | 742 LOG(LS_WARNING) << "Dropping a remote candidate because its ufrag " |
| 743 << candidate.username() | 743 << candidate.username() |
| 744 << " indicates it was for a previous generation."; | 744 << " indicates it was for a previous generation."; |
| 745 return; | 745 return; |
| 746 } | 746 } |
| 747 | 747 |
| (...skipping 43 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 791 LOG(LS_VERBOSE) << "Removed remote candidate " << cand_to_remove.ToString(); | 791 LOG(LS_VERBOSE) << "Removed remote candidate " << cand_to_remove.ToString(); |
| 792 remote_candidates_.erase(iter, remote_candidates_.end()); | 792 remote_candidates_.erase(iter, remote_candidates_.end()); |
| 793 } | 793 } |
| 794 } | 794 } |
| 795 | 795 |
| 796 // Creates connections from all of the ports that we care about to the given | 796 // Creates connections from all of the ports that we care about to the given |
| 797 // remote candidate. The return value is true if we created a connection from | 797 // remote candidate. The return value is true if we created a connection from |
| 798 // the origin port. | 798 // the origin port. |
| 799 bool P2PTransportChannel::CreateConnections(const Candidate& remote_candidate, | 799 bool P2PTransportChannel::CreateConnections(const Candidate& remote_candidate, |
| 800 PortInterface* origin_port) { | 800 PortInterface* origin_port) { |
| 801 ASSERT(network_thread_ == rtc::Thread::Current()); | 801 RTC_DCHECK(network_thread_ == rtc::Thread::Current()); |
| 802 | 802 |
| 803 // If we've already seen the new remote candidate (in the current candidate | 803 // If we've already seen the new remote candidate (in the current candidate |
| 804 // generation), then we shouldn't try creating connections for it. | 804 // generation), then we shouldn't try creating connections for it. |
| 805 // We either already have a connection for it, or we previously created one | 805 // We either already have a connection for it, or we previously created one |
| 806 // and then later pruned it. If we don't return, the channel will again | 806 // and then later pruned it. If we don't return, the channel will again |
| 807 // re-create any connections that were previously pruned, which will then | 807 // re-create any connections that were previously pruned, which will then |
| 808 // immediately be re-pruned, churning the network for no purpose. | 808 // immediately be re-pruned, churning the network for no purpose. |
| 809 // This only applies to candidates received over signaling (i.e. origin_port | 809 // This only applies to candidates received over signaling (i.e. origin_port |
| 810 // is NULL). | 810 // is NULL). |
| 811 if (!origin_port && IsDuplicateRemoteCandidate(remote_candidate)) { | 811 if (!origin_port && IsDuplicateRemoteCandidate(remote_candidate)) { |
| (...skipping 128 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 940 return; | 940 return; |
| 941 } | 941 } |
| 942 | 942 |
| 943 // Try this candidate for all future ports. | 943 // Try this candidate for all future ports. |
| 944 remote_candidates_.push_back(RemoteCandidate(remote_candidate, origin_port)); | 944 remote_candidates_.push_back(RemoteCandidate(remote_candidate, origin_port)); |
| 945 } | 945 } |
| 946 | 946 |
| 947 // Set options on ourselves is simply setting options on all of our available | 947 // Set options on ourselves is simply setting options on all of our available |
| 948 // port objects. | 948 // port objects. |
| 949 int P2PTransportChannel::SetOption(rtc::Socket::Option opt, int value) { | 949 int P2PTransportChannel::SetOption(rtc::Socket::Option opt, int value) { |
| 950 ASSERT(network_thread_ == rtc::Thread::Current()); | 950 RTC_DCHECK(network_thread_ == rtc::Thread::Current()); |
| 951 OptionMap::iterator it = options_.find(opt); | 951 OptionMap::iterator it = options_.find(opt); |
| 952 if (it == options_.end()) { | 952 if (it == options_.end()) { |
| 953 options_.insert(std::make_pair(opt, value)); | 953 options_.insert(std::make_pair(opt, value)); |
| 954 } else if (it->second == value) { | 954 } else if (it->second == value) { |
| 955 return 0; | 955 return 0; |
| 956 } else { | 956 } else { |
| 957 it->second = value; | 957 it->second = value; |
| 958 } | 958 } |
| 959 | 959 |
| 960 for (PortInterface* port : ports_) { | 960 for (PortInterface* port : ports_) { |
| 961 int val = port->SetOption(opt, value); | 961 int val = port->SetOption(opt, value); |
| 962 if (val < 0) { | 962 if (val < 0) { |
| 963 // Because this also occurs deferred, probably no point in reporting an | 963 // Because this also occurs deferred, probably no point in reporting an |
| 964 // error | 964 // error |
| 965 LOG(WARNING) << "SetOption(" << opt << ", " << value | 965 LOG(WARNING) << "SetOption(" << opt << ", " << value |
| 966 << ") failed: " << port->GetError(); | 966 << ") failed: " << port->GetError(); |
| 967 } | 967 } |
| 968 } | 968 } |
| 969 return 0; | 969 return 0; |
| 970 } | 970 } |
| 971 | 971 |
| 972 bool P2PTransportChannel::GetOption(rtc::Socket::Option opt, int* value) { | 972 bool P2PTransportChannel::GetOption(rtc::Socket::Option opt, int* value) { |
| 973 ASSERT(network_thread_ == rtc::Thread::Current()); | 973 RTC_DCHECK(network_thread_ == rtc::Thread::Current()); |
| 974 | 974 |
| 975 const auto& found = options_.find(opt); | 975 const auto& found = options_.find(opt); |
| 976 if (found == options_.end()) { | 976 if (found == options_.end()) { |
| 977 return false; | 977 return false; |
| 978 } | 978 } |
| 979 *value = found->second; | 979 *value = found->second; |
| 980 return true; | 980 return true; |
| 981 } | 981 } |
| 982 | 982 |
| 983 // Send data to the other side, using our selected connection. | 983 // Send data to the other side, using our selected connection. |
| 984 int P2PTransportChannel::SendPacket(const char *data, size_t len, | 984 int P2PTransportChannel::SendPacket(const char *data, size_t len, |
| 985 const rtc::PacketOptions& options, | 985 const rtc::PacketOptions& options, |
| 986 int flags) { | 986 int flags) { |
| 987 ASSERT(network_thread_ == rtc::Thread::Current()); | 987 RTC_DCHECK(network_thread_ == rtc::Thread::Current()); |
| 988 if (flags != 0) { | 988 if (flags != 0) { |
| 989 error_ = EINVAL; | 989 error_ = EINVAL; |
| 990 return -1; | 990 return -1; |
| 991 } | 991 } |
| 992 // If we don't think the connection is working yet, return ENOTCONN | 992 // If we don't think the connection is working yet, return ENOTCONN |
| 993 // instead of sending a packet that will probably be dropped. | 993 // instead of sending a packet that will probably be dropped. |
| 994 if (!ReadyToSend(selected_connection_)) { | 994 if (!ReadyToSend(selected_connection_)) { |
| 995 error_ = ENOTCONN; | 995 error_ = ENOTCONN; |
| 996 return -1; | 996 return -1; |
| 997 } | 997 } |
| 998 | 998 |
| 999 last_sent_packet_id_ = options.packet_id; | 999 last_sent_packet_id_ = options.packet_id; |
| 1000 int sent = selected_connection_->Send(data, len, options); | 1000 int sent = selected_connection_->Send(data, len, options); |
| 1001 if (sent <= 0) { | 1001 if (sent <= 0) { |
| 1002 ASSERT(sent < 0); | 1002 RTC_DCHECK(sent < 0); |
| 1003 error_ = selected_connection_->GetError(); | 1003 error_ = selected_connection_->GetError(); |
| 1004 } | 1004 } |
| 1005 return sent; | 1005 return sent; |
| 1006 } | 1006 } |
| 1007 | 1007 |
| 1008 bool P2PTransportChannel::GetStats(ConnectionInfos *infos) { | 1008 bool P2PTransportChannel::GetStats(ConnectionInfos *infos) { |
| 1009 ASSERT(network_thread_ == rtc::Thread::Current()); | 1009 RTC_DCHECK(network_thread_ == rtc::Thread::Current()); |
| 1010 // Gather connection infos. | 1010 // Gather connection infos. |
| 1011 infos->clear(); | 1011 infos->clear(); |
| 1012 | 1012 |
| 1013 for (Connection* connection : connections_) { | 1013 for (Connection* connection : connections_) { |
| 1014 ConnectionInfo info = connection->stats(); | 1014 ConnectionInfo info = connection->stats(); |
| 1015 info.best_connection = (selected_connection_ == connection); | 1015 info.best_connection = (selected_connection_ == connection); |
| 1016 infos->push_back(std::move(info)); | 1016 infos->push_back(std::move(info)); |
| 1017 connection->set_reported(true); | 1017 connection->set_reported(true); |
| 1018 } | 1018 } |
| 1019 | 1019 |
| (...skipping 194 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1214 return (conn->write_state() == Connection::STATE_WRITE_INIT && | 1214 return (conn->write_state() == Connection::STATE_WRITE_INIT && |
| 1215 config_.presume_writable_when_fully_relayed && | 1215 config_.presume_writable_when_fully_relayed && |
| 1216 conn->local_candidate().type() == RELAY_PORT_TYPE && | 1216 conn->local_candidate().type() == RELAY_PORT_TYPE && |
| 1217 (conn->remote_candidate().type() == RELAY_PORT_TYPE || | 1217 (conn->remote_candidate().type() == RELAY_PORT_TYPE || |
| 1218 conn->remote_candidate().type() == PRFLX_PORT_TYPE)); | 1218 conn->remote_candidate().type() == PRFLX_PORT_TYPE)); |
| 1219 } | 1219 } |
| 1220 | 1220 |
| 1221 // Sort the available connections to find the best one. We also monitor | 1221 // Sort the available connections to find the best one. We also monitor |
| 1222 // the number of available connections and the current state. | 1222 // the number of available connections and the current state. |
| 1223 void P2PTransportChannel::SortConnectionsAndUpdateState() { | 1223 void P2PTransportChannel::SortConnectionsAndUpdateState() { |
| 1224 ASSERT(network_thread_ == rtc::Thread::Current()); | 1224 RTC_DCHECK(network_thread_ == rtc::Thread::Current()); |
| 1225 | 1225 |
| 1226 // Make sure the connection states are up-to-date since this affects how they | 1226 // Make sure the connection states are up-to-date since this affects how they |
| 1227 // will be sorted. | 1227 // will be sorted. |
| 1228 UpdateConnectionStates(); | 1228 UpdateConnectionStates(); |
| 1229 | 1229 |
| 1230 // Any changes after this point will require a re-sort. | 1230 // Any changes after this point will require a re-sort. |
| 1231 sort_dirty_ = false; | 1231 sort_dirty_ = false; |
| 1232 | 1232 |
| 1233 // Find the best alternative connection by sorting. It is important to note | 1233 // Find the best alternative connection by sorting. It is important to note |
| 1234 // that amongst equal preference, writable connections, this will choose the | 1234 // that amongst equal preference, writable connections, this will choose the |
| (...skipping 302 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1537 conn->active(); | 1537 conn->active(); |
| 1538 } | 1538 } |
| 1539 | 1539 |
| 1540 // Is the connection in a state for us to even consider pinging the other side? | 1540 // Is the connection in a state for us to even consider pinging the other side? |
| 1541 // We consider a connection pingable even if it's not connected because that's | 1541 // We consider a connection pingable even if it's not connected because that's |
| 1542 // how a TCP connection is kicked into reconnecting on the active side. | 1542 // how a TCP connection is kicked into reconnecting on the active side. |
| 1543 bool P2PTransportChannel::IsPingable(const Connection* conn, | 1543 bool P2PTransportChannel::IsPingable(const Connection* conn, |
| 1544 int64_t now) const { | 1544 int64_t now) const { |
| 1545 const Candidate& remote = conn->remote_candidate(); | 1545 const Candidate& remote = conn->remote_candidate(); |
| 1546 // We should never get this far with an empty remote ufrag. | 1546 // We should never get this far with an empty remote ufrag. |
| 1547 ASSERT(!remote.username().empty()); | 1547 RTC_DCHECK(!remote.username().empty()); |
| 1548 if (remote.username().empty() || remote.password().empty()) { | 1548 if (remote.username().empty() || remote.password().empty()) { |
| 1549 // If we don't have an ICE ufrag and pwd, there's no way we can ping. | 1549 // If we don't have an ICE ufrag and pwd, there's no way we can ping. |
| 1550 return false; | 1550 return false; |
| 1551 } | 1551 } |
| 1552 | 1552 |
| 1553 // A failed connection will not be pinged. | 1553 // A failed connection will not be pinged. |
| 1554 if (conn->state() == IceCandidatePairState::FAILED) { | 1554 if (conn->state() == IceCandidatePairState::FAILED) { |
| 1555 return false; | 1555 return false; |
| 1556 } | 1556 } |
| 1557 | 1557 |
| (...skipping 203 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1761 default: | 1761 default: |
| 1762 RTC_DCHECK(false); | 1762 RTC_DCHECK(false); |
| 1763 return false; | 1763 return false; |
| 1764 } | 1764 } |
| 1765 } | 1765 } |
| 1766 | 1766 |
| 1767 // When a connection's state changes, we need to figure out who to use as | 1767 // When a connection's state changes, we need to figure out who to use as |
| 1768 // the selected connection again. It could have become usable, or become | 1768 // the selected connection again. It could have become usable, or become |
| 1769 // unusable. | 1769 // unusable. |
| 1770 void P2PTransportChannel::OnConnectionStateChange(Connection* connection) { | 1770 void P2PTransportChannel::OnConnectionStateChange(Connection* connection) { |
| 1771 ASSERT(network_thread_ == rtc::Thread::Current()); | 1771 RTC_DCHECK(network_thread_ == rtc::Thread::Current()); |
| 1772 | 1772 |
| 1773 // May stop the allocator session when at least one connection becomes | 1773 // May stop the allocator session when at least one connection becomes |
| 1774 // strongly connected after starting to get ports and the local candidate of | 1774 // strongly connected after starting to get ports and the local candidate of |
| 1775 // the connection is at the latest generation. It is not enough to check | 1775 // the connection is at the latest generation. It is not enough to check |
| 1776 // that the connection becomes weakly connected because the connection may be | 1776 // that the connection becomes weakly connected because the connection may be |
| 1777 // changing from (writable, receiving) to (writable, not receiving). | 1777 // changing from (writable, receiving) to (writable, not receiving). |
| 1778 bool strongly_connected = !connection->weak(); | 1778 bool strongly_connected = !connection->weak(); |
| 1779 bool latest_generation = connection->local_candidate().generation() >= | 1779 bool latest_generation = connection->local_candidate().generation() >= |
| 1780 allocator_session()->generation(); | 1780 allocator_session()->generation(); |
| 1781 if (strongly_connected && latest_generation) { | 1781 if (strongly_connected && latest_generation) { |
| 1782 MaybeStopPortAllocatorSessions(); | 1782 MaybeStopPortAllocatorSessions(); |
| 1783 } | 1783 } |
| 1784 | 1784 |
| 1785 // We have to unroll the stack before doing this because we may be changing | 1785 // We have to unroll the stack before doing this because we may be changing |
| 1786 // the state of connections while sorting. | 1786 // the state of connections while sorting. |
| 1787 RequestSortAndStateUpdate(); | 1787 RequestSortAndStateUpdate(); |
| 1788 } | 1788 } |
| 1789 | 1789 |
| 1790 // When a connection is removed, edit it out, and then update our best | 1790 // When a connection is removed, edit it out, and then update our best |
| 1791 // connection. | 1791 // connection. |
| 1792 void P2PTransportChannel::OnConnectionDestroyed(Connection* connection) { | 1792 void P2PTransportChannel::OnConnectionDestroyed(Connection* connection) { |
| 1793 ASSERT(network_thread_ == rtc::Thread::Current()); | 1793 RTC_DCHECK(network_thread_ == rtc::Thread::Current()); |
| 1794 | 1794 |
| 1795 // Note: the previous selected_connection_ may be destroyed by now, so don't | 1795 // Note: the previous selected_connection_ may be destroyed by now, so don't |
| 1796 // use it. | 1796 // use it. |
| 1797 | 1797 |
| 1798 // Remove this connection from the list. | 1798 // Remove this connection from the list. |
| 1799 std::vector<Connection*>::iterator iter = | 1799 std::vector<Connection*>::iterator iter = |
| 1800 std::find(connections_.begin(), connections_.end(), connection); | 1800 std::find(connections_.begin(), connections_.end(), connection); |
| 1801 ASSERT(iter != connections_.end()); | 1801 RTC_DCHECK(iter != connections_.end()); |
| 1802 pinged_connections_.erase(*iter); | 1802 pinged_connections_.erase(*iter); |
| 1803 unpinged_connections_.erase(*iter); | 1803 unpinged_connections_.erase(*iter); |
| 1804 connections_.erase(iter); | 1804 connections_.erase(iter); |
| 1805 | 1805 |
| 1806 LOG_J(LS_INFO, this) << "Removed connection " << std::hex << connection | 1806 LOG_J(LS_INFO, this) << "Removed connection " << std::hex << connection |
| 1807 << std::dec << " (" << connections_.size() | 1807 << std::dec << " (" << connections_.size() |
| 1808 << " remaining)"; | 1808 << " remaining)"; |
| 1809 | 1809 |
| 1810 // If this is currently the selected connection, then we need to pick a new | 1810 // If this is currently the selected connection, then we need to pick a new |
| 1811 // one. The call to SortConnectionsAndUpdateState will pick a new one. It | 1811 // one. The call to SortConnectionsAndUpdateState will pick a new one. It |
| 1812 // looks at the current selected connection in order to avoid switching | 1812 // looks at the current selected connection in order to avoid switching |
| 1813 // between fairly similar ones. Since this connection is no longer an option, | 1813 // between fairly similar ones. Since this connection is no longer an option, |
| 1814 // we can just set selected to nullptr and re-choose a best assuming that | 1814 // we can just set selected to nullptr and re-choose a best assuming that |
| 1815 // there was no selected connection. | 1815 // there was no selected connection. |
| 1816 if (selected_connection_ == connection) { | 1816 if (selected_connection_ == connection) { |
| 1817 LOG(LS_INFO) << "Selected connection destroyed. Will choose a new one."; | 1817 LOG(LS_INFO) << "Selected connection destroyed. Will choose a new one."; |
| 1818 SwitchSelectedConnection(nullptr); | 1818 SwitchSelectedConnection(nullptr); |
| 1819 RequestSortAndStateUpdate(); | 1819 RequestSortAndStateUpdate(); |
| 1820 } else { | 1820 } else { |
| 1821 // If a non-selected connection was destroyed, we don't need to re-sort but | 1821 // If a non-selected connection was destroyed, we don't need to re-sort but |
| 1822 // we do need to update state, because we could be switching to "failed" or | 1822 // we do need to update state, because we could be switching to "failed" or |
| 1823 // "completed". | 1823 // "completed". |
| 1824 UpdateState(); | 1824 UpdateState(); |
| 1825 } | 1825 } |
| 1826 } | 1826 } |
| 1827 | 1827 |
| 1828 // When a port is destroyed, remove it from our list of ports to use for | 1828 // When a port is destroyed, remove it from our list of ports to use for |
| 1829 // connection attempts. | 1829 // connection attempts. |
| 1830 void P2PTransportChannel::OnPortDestroyed(PortInterface* port) { | 1830 void P2PTransportChannel::OnPortDestroyed(PortInterface* port) { |
| 1831 ASSERT(network_thread_ == rtc::Thread::Current()); | 1831 RTC_DCHECK(network_thread_ == rtc::Thread::Current()); |
| 1832 | 1832 |
| 1833 ports_.erase(std::remove(ports_.begin(), ports_.end(), port), ports_.end()); | 1833 ports_.erase(std::remove(ports_.begin(), ports_.end(), port), ports_.end()); |
| 1834 pruned_ports_.erase( | 1834 pruned_ports_.erase( |
| 1835 std::remove(pruned_ports_.begin(), pruned_ports_.end(), port), | 1835 std::remove(pruned_ports_.begin(), pruned_ports_.end(), port), |
| 1836 pruned_ports_.end()); | 1836 pruned_ports_.end()); |
| 1837 LOG(INFO) << "Removed port because it is destroyed: " << ports_.size() | 1837 LOG(INFO) << "Removed port because it is destroyed: " << ports_.size() |
| 1838 << " remaining"; | 1838 << " remaining"; |
| 1839 } | 1839 } |
| 1840 | 1840 |
| 1841 void P2PTransportChannel::OnPortsPruned( | 1841 void P2PTransportChannel::OnPortsPruned( |
| 1842 PortAllocatorSession* session, | 1842 PortAllocatorSession* session, |
| 1843 const std::vector<PortInterface*>& ports) { | 1843 const std::vector<PortInterface*>& ports) { |
| 1844 ASSERT(network_thread_ == rtc::Thread::Current()); | 1844 RTC_DCHECK(network_thread_ == rtc::Thread::Current()); |
| 1845 for (PortInterface* port : ports) { | 1845 for (PortInterface* port : ports) { |
| 1846 if (PrunePort(port)) { | 1846 if (PrunePort(port)) { |
| 1847 LOG(INFO) << "Removed port: " << port->ToString() << " " << ports_.size() | 1847 LOG(INFO) << "Removed port: " << port->ToString() << " " << ports_.size() |
| 1848 << " remaining"; | 1848 << " remaining"; |
| 1849 } | 1849 } |
| 1850 } | 1850 } |
| 1851 } | 1851 } |
| 1852 | 1852 |
| 1853 void P2PTransportChannel::OnCandidatesRemoved( | 1853 void P2PTransportChannel::OnCandidatesRemoved( |
| 1854 PortAllocatorSession* session, | 1854 PortAllocatorSession* session, |
| 1855 const std::vector<Candidate>& candidates) { | 1855 const std::vector<Candidate>& candidates) { |
| 1856 ASSERT(network_thread_ == rtc::Thread::Current()); | 1856 RTC_DCHECK(network_thread_ == rtc::Thread::Current()); |
| 1857 // Do not signal candidate removals if continual gathering is not enabled, or | 1857 // Do not signal candidate removals if continual gathering is not enabled, or |
| 1858 // if this is not the last session because an ICE restart would have signaled | 1858 // if this is not the last session because an ICE restart would have signaled |
| 1859 // the remote side to remove all candidates in previous sessions. | 1859 // the remote side to remove all candidates in previous sessions. |
| 1860 if (!config_.gather_continually() || session != allocator_session()) { | 1860 if (!config_.gather_continually() || session != allocator_session()) { |
| 1861 return; | 1861 return; |
| 1862 } | 1862 } |
| 1863 | 1863 |
| 1864 std::vector<Candidate> candidates_to_remove; | 1864 std::vector<Candidate> candidates_to_remove; |
| 1865 for (Candidate candidate : candidates) { | 1865 for (Candidate candidate : candidates) { |
| 1866 candidate.set_transport_name(transport_name()); | 1866 candidate.set_transport_name(transport_name()); |
| (...skipping 29 matching lines...) Expand all Loading... |
| 1896 ports_.erase(it); | 1896 ports_.erase(it); |
| 1897 pruned_ports_.push_back(port); | 1897 pruned_ports_.push_back(port); |
| 1898 return true; | 1898 return true; |
| 1899 } | 1899 } |
| 1900 | 1900 |
| 1901 // We data is available, let listeners know | 1901 // We data is available, let listeners know |
| 1902 void P2PTransportChannel::OnReadPacket(Connection* connection, | 1902 void P2PTransportChannel::OnReadPacket(Connection* connection, |
| 1903 const char* data, | 1903 const char* data, |
| 1904 size_t len, | 1904 size_t len, |
| 1905 const rtc::PacketTime& packet_time) { | 1905 const rtc::PacketTime& packet_time) { |
| 1906 ASSERT(network_thread_ == rtc::Thread::Current()); | 1906 RTC_DCHECK(network_thread_ == rtc::Thread::Current()); |
| 1907 | 1907 |
| 1908 // Do not deliver, if packet doesn't belong to the correct transport channel. | 1908 // Do not deliver, if packet doesn't belong to the correct transport channel. |
| 1909 if (!FindConnection(connection)) | 1909 if (!FindConnection(connection)) |
| 1910 return; | 1910 return; |
| 1911 | 1911 |
| 1912 // Let the client know of an incoming packet | 1912 // Let the client know of an incoming packet |
| 1913 SignalReadPacket(this, data, len, packet_time, 0); | 1913 SignalReadPacket(this, data, len, packet_time, 0); |
| 1914 | 1914 |
| 1915 // May need to switch the sending connection based on the receiving media path | 1915 // May need to switch the sending connection based on the receiving media path |
| 1916 // if this is the controlled side. | 1916 // if this is the controlled side. |
| 1917 if (ice_role_ == ICEROLE_CONTROLLED) { | 1917 if (ice_role_ == ICEROLE_CONTROLLED) { |
| 1918 MaybeSwitchSelectedConnection(connection, "data received"); | 1918 MaybeSwitchSelectedConnection(connection, "data received"); |
| 1919 } | 1919 } |
| 1920 } | 1920 } |
| 1921 | 1921 |
| 1922 void P2PTransportChannel::OnSentPacket(const rtc::SentPacket& sent_packet) { | 1922 void P2PTransportChannel::OnSentPacket(const rtc::SentPacket& sent_packet) { |
| 1923 ASSERT(network_thread_ == rtc::Thread::Current()); | 1923 RTC_DCHECK(network_thread_ == rtc::Thread::Current()); |
| 1924 | 1924 |
| 1925 SignalSentPacket(this, sent_packet); | 1925 SignalSentPacket(this, sent_packet); |
| 1926 } | 1926 } |
| 1927 | 1927 |
| 1928 void P2PTransportChannel::OnReadyToSend(Connection* connection) { | 1928 void P2PTransportChannel::OnReadyToSend(Connection* connection) { |
| 1929 if (connection == selected_connection_ && writable()) { | 1929 if (connection == selected_connection_ && writable()) { |
| 1930 SignalReadyToSend(this); | 1930 SignalReadyToSend(this); |
| 1931 } | 1931 } |
| 1932 } | 1932 } |
| 1933 | 1933 |
| (...skipping 74 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2008 | 2008 |
| 2009 // During the initial state when nothing has been pinged yet, return the first | 2009 // During the initial state when nothing has been pinged yet, return the first |
| 2010 // one in the ordered |connections_|. | 2010 // one in the ordered |connections_|. |
| 2011 return *(std::find_if(connections_.begin(), connections_.end(), | 2011 return *(std::find_if(connections_.begin(), connections_.end(), |
| 2012 [conn1, conn2](Connection* conn) { | 2012 [conn1, conn2](Connection* conn) { |
| 2013 return conn == conn1 || conn == conn2; | 2013 return conn == conn1 || conn == conn2; |
| 2014 })); | 2014 })); |
| 2015 } | 2015 } |
| 2016 | 2016 |
| 2017 } // namespace cricket | 2017 } // namespace cricket |
| OLD | NEW |