| 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 84 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 95 int component, | 95 int component, |
| 96 P2PTransport* transport, | 96 P2PTransport* transport, |
| 97 PortAllocator* allocator) | 97 PortAllocator* allocator) |
| 98 : P2PTransportChannel(transport_name, component, allocator) {} | 98 : P2PTransportChannel(transport_name, component, allocator) {} |
| 99 | 99 |
| 100 P2PTransportChannel::P2PTransportChannel(const std::string& transport_name, | 100 P2PTransportChannel::P2PTransportChannel(const std::string& transport_name, |
| 101 int component, | 101 int component, |
| 102 PortAllocator* allocator) | 102 PortAllocator* allocator) |
| 103 : TransportChannelImpl(transport_name, component), | 103 : TransportChannelImpl(transport_name, component), |
| 104 allocator_(allocator), | 104 allocator_(allocator), |
| 105 worker_thread_(rtc::Thread::Current()), | 105 network_thread_(rtc::Thread::Current()), |
| 106 incoming_only_(false), | 106 incoming_only_(false), |
| 107 error_(0), | 107 error_(0), |
| 108 sort_dirty_(false), | 108 sort_dirty_(false), |
| 109 remote_ice_mode_(ICEMODE_FULL), | 109 remote_ice_mode_(ICEMODE_FULL), |
| 110 ice_role_(ICEROLE_UNKNOWN), | 110 ice_role_(ICEROLE_UNKNOWN), |
| 111 tiebreaker_(0), | 111 tiebreaker_(0), |
| 112 gathering_state_(kIceGatheringNew), | 112 gathering_state_(kIceGatheringNew), |
| 113 check_receiving_interval_(MIN_CHECK_RECEIVING_INTERVAL * 5), | 113 check_receiving_interval_(MIN_CHECK_RECEIVING_INTERVAL * 5), |
| 114 config_(MIN_CHECK_RECEIVING_INTERVAL * 50 /* receiving_timeout */, | 114 config_(MIN_CHECK_RECEIVING_INTERVAL * 50 /* receiving_timeout */, |
| 115 DEFAULT_BACKUP_CONNECTION_PING_INTERVAL, | 115 DEFAULT_BACKUP_CONNECTION_PING_INTERVAL, |
| 116 GATHER_ONCE /* continual_gathering_policy */, | 116 GATHER_ONCE /* continual_gathering_policy */, |
| 117 false /* prioritize_most_likely_candidate_pairs */, | 117 false /* prioritize_most_likely_candidate_pairs */, |
| 118 STABLE_WRITABLE_CONNECTION_PING_INTERVAL, | 118 STABLE_WRITABLE_CONNECTION_PING_INTERVAL, |
| 119 true /* presume_writable_when_fully_relayed */, | 119 true /* presume_writable_when_fully_relayed */, |
| 120 DEFAULT_REGATHER_ON_FAILED_NETWORKS_INTERVAL, | 120 DEFAULT_REGATHER_ON_FAILED_NETWORKS_INTERVAL, |
| 121 RECEIVING_SWITCHING_DELAY) { | 121 RECEIVING_SWITCHING_DELAY) { |
| 122 uint32_t weak_ping_interval = ::strtoul( | 122 uint32_t weak_ping_interval = ::strtoul( |
| 123 webrtc::field_trial::FindFullName("WebRTC-StunInterPacketDelay").c_str(), | 123 webrtc::field_trial::FindFullName("WebRTC-StunInterPacketDelay").c_str(), |
| 124 nullptr, 10); | 124 nullptr, 10); |
| 125 if (weak_ping_interval) { | 125 if (weak_ping_interval) { |
| 126 weak_ping_interval_ = static_cast<int>(weak_ping_interval); | 126 weak_ping_interval_ = static_cast<int>(weak_ping_interval); |
| 127 } | 127 } |
| 128 } | 128 } |
| 129 | 129 |
| 130 P2PTransportChannel::~P2PTransportChannel() { | 130 P2PTransportChannel::~P2PTransportChannel() { |
| 131 ASSERT(worker_thread_ == rtc::Thread::Current()); | 131 ASSERT(network_thread_ == rtc::Thread::Current()); |
| 132 } | 132 } |
| 133 | 133 |
| 134 // Add the allocator session to our list so that we know which sessions | 134 // Add the allocator session to our list so that we know which sessions |
| 135 // are still active. | 135 // are still active. |
| 136 void P2PTransportChannel::AddAllocatorSession( | 136 void P2PTransportChannel::AddAllocatorSession( |
| 137 std::unique_ptr<PortAllocatorSession> session) { | 137 std::unique_ptr<PortAllocatorSession> session) { |
| 138 ASSERT(worker_thread_ == rtc::Thread::Current()); | 138 ASSERT(network_thread_ == rtc::Thread::Current()); |
| 139 | 139 |
| 140 session->set_generation(static_cast<uint32_t>(allocator_sessions_.size())); | 140 session->set_generation(static_cast<uint32_t>(allocator_sessions_.size())); |
| 141 session->SignalPortReady.connect(this, &P2PTransportChannel::OnPortReady); | 141 session->SignalPortReady.connect(this, &P2PTransportChannel::OnPortReady); |
| 142 session->SignalPortsPruned.connect(this, &P2PTransportChannel::OnPortsPruned); | 142 session->SignalPortsPruned.connect(this, &P2PTransportChannel::OnPortsPruned); |
| 143 session->SignalCandidatesReady.connect( | 143 session->SignalCandidatesReady.connect( |
| 144 this, &P2PTransportChannel::OnCandidatesReady); | 144 this, &P2PTransportChannel::OnCandidatesReady); |
| 145 session->SignalCandidatesRemoved.connect( | 145 session->SignalCandidatesRemoved.connect( |
| 146 this, &P2PTransportChannel::OnCandidatesRemoved); | 146 this, &P2PTransportChannel::OnCandidatesRemoved); |
| 147 session->SignalCandidatesAllocationDone.connect( | 147 session->SignalCandidatesAllocationDone.connect( |
| 148 this, &P2PTransportChannel::OnCandidatesAllocationDone); | 148 this, &P2PTransportChannel::OnCandidatesAllocationDone); |
| (...skipping 90 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 239 // threshold, the new connection is in a better receiving state than the | 239 // threshold, the new connection is in a better receiving state than the |
| 240 // currently selected connection. So we need to re-check whether it needs | 240 // currently selected connection. So we need to re-check whether it needs |
| 241 // to be switched at a later time. | 241 // to be switched at a later time. |
| 242 thread()->PostDelayed(RTC_FROM_HERE, *config_.receiving_switching_delay, | 242 thread()->PostDelayed(RTC_FROM_HERE, *config_.receiving_switching_delay, |
| 243 this, MSG_SORT_AND_UPDATE_STATE); | 243 this, MSG_SORT_AND_UPDATE_STATE); |
| 244 } | 244 } |
| 245 return false; | 245 return false; |
| 246 } | 246 } |
| 247 | 247 |
| 248 void P2PTransportChannel::SetIceRole(IceRole ice_role) { | 248 void P2PTransportChannel::SetIceRole(IceRole ice_role) { |
| 249 ASSERT(worker_thread_ == rtc::Thread::Current()); | 249 ASSERT(network_thread_ == rtc::Thread::Current()); |
| 250 if (ice_role_ != ice_role) { | 250 if (ice_role_ != ice_role) { |
| 251 ice_role_ = ice_role; | 251 ice_role_ = ice_role; |
| 252 for (PortInterface* port : ports_) { | 252 for (PortInterface* port : ports_) { |
| 253 port->SetIceRole(ice_role); | 253 port->SetIceRole(ice_role); |
| 254 } | 254 } |
| 255 // Update role on pruned ports as well, because they may still have | 255 // Update role on pruned ports as well, because they may still have |
| 256 // connections alive that should be using the correct role. | 256 // connections alive that should be using the correct role. |
| 257 for (PortInterface* port : pruned_ports_) { | 257 for (PortInterface* port : pruned_ports_) { |
| 258 port->SetIceRole(ice_role); | 258 port->SetIceRole(ice_role); |
| 259 } | 259 } |
| 260 } | 260 } |
| 261 } | 261 } |
| 262 | 262 |
| 263 void P2PTransportChannel::SetIceTiebreaker(uint64_t tiebreaker) { | 263 void P2PTransportChannel::SetIceTiebreaker(uint64_t tiebreaker) { |
| 264 ASSERT(worker_thread_ == rtc::Thread::Current()); | 264 ASSERT(network_thread_ == rtc::Thread::Current()); |
| 265 if (!ports_.empty() || !pruned_ports_.empty()) { | 265 if (!ports_.empty() || !pruned_ports_.empty()) { |
| 266 LOG(LS_ERROR) | 266 LOG(LS_ERROR) |
| 267 << "Attempt to change tiebreaker after Port has been allocated."; | 267 << "Attempt to change tiebreaker after Port has been allocated."; |
| 268 return; | 268 return; |
| 269 } | 269 } |
| 270 | 270 |
| 271 tiebreaker_ = tiebreaker; | 271 tiebreaker_ = tiebreaker; |
| 272 } | 272 } |
| 273 | 273 |
| 274 TransportChannelState P2PTransportChannel::GetState() const { | 274 TransportChannelState P2PTransportChannel::GetState() const { |
| (...skipping 27 matching lines...) Expand all Loading... |
| 302 << network->ToString() | 302 << network->ToString() |
| 303 << " has more than 1 connection."; | 303 << " has more than 1 connection."; |
| 304 return TransportChannelState::STATE_CONNECTING; | 304 return TransportChannelState::STATE_CONNECTING; |
| 305 } | 305 } |
| 306 } | 306 } |
| 307 | 307 |
| 308 return TransportChannelState::STATE_COMPLETED; | 308 return TransportChannelState::STATE_COMPLETED; |
| 309 } | 309 } |
| 310 | 310 |
| 311 void P2PTransportChannel::SetIceParameters(const IceParameters& ice_params) { | 311 void P2PTransportChannel::SetIceParameters(const IceParameters& ice_params) { |
| 312 ASSERT(worker_thread_ == rtc::Thread::Current()); | 312 ASSERT(network_thread_ == rtc::Thread::Current()); |
| 313 LOG(LS_INFO) << "Set ICE ufrag: " << ice_params.ufrag | 313 LOG(LS_INFO) << "Set ICE ufrag: " << ice_params.ufrag |
| 314 << " pwd: " << ice_params.pwd << " on transport " | 314 << " pwd: " << ice_params.pwd << " on transport " |
| 315 << transport_name(); | 315 << transport_name(); |
| 316 ice_parameters_ = ice_params; | 316 ice_parameters_ = ice_params; |
| 317 // Note: Candidate gathering will restart when MaybeStartGathering is next | 317 // Note: Candidate gathering will restart when MaybeStartGathering is next |
| 318 // called. | 318 // called. |
| 319 } | 319 } |
| 320 | 320 |
| 321 void P2PTransportChannel::SetRemoteIceParameters( | 321 void P2PTransportChannel::SetRemoteIceParameters( |
| 322 const IceParameters& ice_params) { | 322 const IceParameters& ice_params) { |
| 323 ASSERT(worker_thread_ == rtc::Thread::Current()); | 323 ASSERT(network_thread_ == rtc::Thread::Current()); |
| 324 LOG(LS_INFO) << "Remote supports ICE renomination ? " | 324 LOG(LS_INFO) << "Remote supports ICE renomination ? " |
| 325 << ice_params.renomination; | 325 << ice_params.renomination; |
| 326 IceParameters* current_ice = remote_ice(); | 326 IceParameters* current_ice = remote_ice(); |
| 327 if (!current_ice || *current_ice != ice_params) { | 327 if (!current_ice || *current_ice != ice_params) { |
| 328 // Keep the ICE credentials so that newer connections | 328 // Keep the ICE credentials so that newer connections |
| 329 // are prioritized over the older ones. | 329 // are prioritized over the older ones. |
| 330 remote_ice_parameters_.push_back(ice_params); | 330 remote_ice_parameters_.push_back(ice_params); |
| 331 } | 331 } |
| 332 | 332 |
| 333 // Update the pwd of remote candidate if needed. | 333 // Update the pwd of remote candidate if needed. |
| (...skipping 141 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 475 ice_parameters_.pwd)); | 475 ice_parameters_.pwd)); |
| 476 LOG(LS_INFO) << "Start getting ports"; | 476 LOG(LS_INFO) << "Start getting ports"; |
| 477 allocator_sessions_.back()->StartGettingPorts(); | 477 allocator_sessions_.back()->StartGettingPorts(); |
| 478 } | 478 } |
| 479 } | 479 } |
| 480 } | 480 } |
| 481 | 481 |
| 482 // A new port is available, attempt to make connections for it | 482 // A new port is available, attempt to make connections for it |
| 483 void P2PTransportChannel::OnPortReady(PortAllocatorSession *session, | 483 void P2PTransportChannel::OnPortReady(PortAllocatorSession *session, |
| 484 PortInterface* port) { | 484 PortInterface* port) { |
| 485 ASSERT(worker_thread_ == rtc::Thread::Current()); | 485 ASSERT(network_thread_ == rtc::Thread::Current()); |
| 486 | 486 |
| 487 // Set in-effect options on the new port | 487 // Set in-effect options on the new port |
| 488 for (OptionMap::const_iterator it = options_.begin(); | 488 for (OptionMap::const_iterator it = options_.begin(); |
| 489 it != options_.end(); | 489 it != options_.end(); |
| 490 ++it) { | 490 ++it) { |
| 491 int val = port->SetOption(it->first, it->second); | 491 int val = port->SetOption(it->first, it->second); |
| 492 if (val < 0) { | 492 if (val < 0) { |
| 493 LOG_J(LS_WARNING, port) << "SetOption(" << it->first | 493 LOG_J(LS_WARNING, port) << "SetOption(" << it->first |
| 494 << ", " << it->second | 494 << ", " << it->second |
| 495 << ") failed: " << port->GetError(); | 495 << ") failed: " << port->GetError(); |
| (...skipping 24 matching lines...) Expand all Loading... |
| 520 CreateConnection(port, *iter, iter->origin_port()); | 520 CreateConnection(port, *iter, iter->origin_port()); |
| 521 } | 521 } |
| 522 | 522 |
| 523 SortConnectionsAndUpdateState(); | 523 SortConnectionsAndUpdateState(); |
| 524 } | 524 } |
| 525 | 525 |
| 526 // A new candidate is available, let listeners know | 526 // A new candidate is available, let listeners know |
| 527 void P2PTransportChannel::OnCandidatesReady( | 527 void P2PTransportChannel::OnCandidatesReady( |
| 528 PortAllocatorSession* session, | 528 PortAllocatorSession* session, |
| 529 const std::vector<Candidate>& candidates) { | 529 const std::vector<Candidate>& candidates) { |
| 530 ASSERT(worker_thread_ == rtc::Thread::Current()); | 530 ASSERT(network_thread_ == rtc::Thread::Current()); |
| 531 for (size_t i = 0; i < candidates.size(); ++i) { | 531 for (size_t i = 0; i < candidates.size(); ++i) { |
| 532 SignalCandidateGathered(this, candidates[i]); | 532 SignalCandidateGathered(this, candidates[i]); |
| 533 } | 533 } |
| 534 } | 534 } |
| 535 | 535 |
| 536 void P2PTransportChannel::OnCandidatesAllocationDone( | 536 void P2PTransportChannel::OnCandidatesAllocationDone( |
| 537 PortAllocatorSession* session) { | 537 PortAllocatorSession* session) { |
| 538 ASSERT(worker_thread_ == rtc::Thread::Current()); | 538 ASSERT(network_thread_ == rtc::Thread::Current()); |
| 539 if (config_.gather_continually()) { | 539 if (config_.gather_continually()) { |
| 540 LOG(LS_INFO) << "P2PTransportChannel: " << transport_name() | 540 LOG(LS_INFO) << "P2PTransportChannel: " << transport_name() |
| 541 << ", component " << component() | 541 << ", component " << component() |
| 542 << " gathering complete, but using continual " | 542 << " gathering complete, but using continual " |
| 543 << "gathering so not changing gathering state."; | 543 << "gathering so not changing gathering state."; |
| 544 return; | 544 return; |
| 545 } | 545 } |
| 546 gathering_state_ = kIceGatheringComplete; | 546 gathering_state_ = kIceGatheringComplete; |
| 547 LOG(LS_INFO) << "P2PTransportChannel: " << transport_name() << ", component " | 547 LOG(LS_INFO) << "P2PTransportChannel: " << transport_name() << ", component " |
| 548 << component() << " gathering complete"; | 548 << component() << " gathering complete"; |
| 549 SignalGatheringState(this); | 549 SignalGatheringState(this); |
| 550 } | 550 } |
| 551 | 551 |
| 552 // Handle stun packets | 552 // Handle stun packets |
| 553 void P2PTransportChannel::OnUnknownAddress( | 553 void P2PTransportChannel::OnUnknownAddress( |
| 554 PortInterface* port, | 554 PortInterface* port, |
| 555 const rtc::SocketAddress& address, ProtocolType proto, | 555 const rtc::SocketAddress& address, ProtocolType proto, |
| 556 IceMessage* stun_msg, const std::string &remote_username, | 556 IceMessage* stun_msg, const std::string &remote_username, |
| 557 bool port_muxed) { | 557 bool port_muxed) { |
| 558 ASSERT(worker_thread_ == rtc::Thread::Current()); | 558 ASSERT(network_thread_ == rtc::Thread::Current()); |
| 559 | 559 |
| 560 // Port has received a valid stun packet from an address that no Connection | 560 // Port has received a valid stun packet from an address that no Connection |
| 561 // is currently available for. See if we already have a candidate with the | 561 // is currently available for. See if we already have a candidate with the |
| 562 // address. If it isn't we need to create new candidate for it. | 562 // address. If it isn't we need to create new candidate for it. |
| 563 | 563 |
| 564 const Candidate* candidate = nullptr; | 564 const Candidate* candidate = nullptr; |
| 565 for (const Candidate& c : remote_candidates_) { | 565 for (const Candidate& c : remote_candidates_) { |
| 566 if (c.username() == remote_username && c.address() == address && | 566 if (c.username() == remote_username && c.address() == address && |
| 567 c.protocol() == ProtoToString(proto)) { | 567 c.protocol() == ProtoToString(proto)) { |
| 568 candidate = &c; | 568 candidate = &c; |
| (...skipping 118 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 687 [ufrag](const IceParameters& param) { return param.ufrag == ufrag; }); | 687 [ufrag](const IceParameters& param) { return param.ufrag == ufrag; }); |
| 688 if (it == params.rend()) { | 688 if (it == params.rend()) { |
| 689 // Not found. | 689 // Not found. |
| 690 return nullptr; | 690 return nullptr; |
| 691 } | 691 } |
| 692 *generation = params.rend() - it - 1; | 692 *generation = params.rend() - it - 1; |
| 693 return &(*it); | 693 return &(*it); |
| 694 } | 694 } |
| 695 | 695 |
| 696 void P2PTransportChannel::OnNominated(Connection* conn) { | 696 void P2PTransportChannel::OnNominated(Connection* conn) { |
| 697 ASSERT(worker_thread_ == rtc::Thread::Current()); | 697 ASSERT(network_thread_ == rtc::Thread::Current()); |
| 698 ASSERT(ice_role_ == ICEROLE_CONTROLLED); | 698 ASSERT(ice_role_ == ICEROLE_CONTROLLED); |
| 699 | 699 |
| 700 if (selected_connection_ == conn) { | 700 if (selected_connection_ == conn) { |
| 701 return; | 701 return; |
| 702 } | 702 } |
| 703 | 703 |
| 704 if (MaybeSwitchSelectedConnection(conn, | 704 if (MaybeSwitchSelectedConnection(conn, |
| 705 "nomination on the controlled side")) { | 705 "nomination on the controlled side")) { |
| 706 // Now that we have selected a connection, it is time to prune other | 706 // Now that we have selected a connection, it is time to prune other |
| 707 // connections and update the read/write state of the channel. | 707 // connections and update the read/write state of the channel. |
| 708 RequestSortAndStateUpdate(); | 708 RequestSortAndStateUpdate(); |
| 709 } else { | 709 } else { |
| 710 LOG(LS_INFO) | 710 LOG(LS_INFO) |
| 711 << "Not switching the selected connection on controlled side yet: " | 711 << "Not switching the selected connection on controlled side yet: " |
| 712 << conn->ToString(); | 712 << conn->ToString(); |
| 713 } | 713 } |
| 714 } | 714 } |
| 715 | 715 |
| 716 void P2PTransportChannel::AddRemoteCandidate(const Candidate& candidate) { | 716 void P2PTransportChannel::AddRemoteCandidate(const Candidate& candidate) { |
| 717 ASSERT(worker_thread_ == rtc::Thread::Current()); | 717 ASSERT(network_thread_ == rtc::Thread::Current()); |
| 718 | 718 |
| 719 uint32_t generation = GetRemoteCandidateGeneration(candidate); | 719 uint32_t generation = GetRemoteCandidateGeneration(candidate); |
| 720 // If a remote candidate with a previous generation arrives, drop it. | 720 // If a remote candidate with a previous generation arrives, drop it. |
| 721 if (generation < remote_ice_generation()) { | 721 if (generation < remote_ice_generation()) { |
| 722 LOG(LS_WARNING) << "Dropping a remote candidate because its ufrag " | 722 LOG(LS_WARNING) << "Dropping a remote candidate because its ufrag " |
| 723 << candidate.username() | 723 << candidate.username() |
| 724 << " indicates it was for a previous generation."; | 724 << " indicates it was for a previous generation."; |
| 725 return; | 725 return; |
| 726 } | 726 } |
| 727 | 727 |
| (...skipping 43 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 771 LOG(LS_VERBOSE) << "Removed remote candidate " << cand_to_remove.ToString(); | 771 LOG(LS_VERBOSE) << "Removed remote candidate " << cand_to_remove.ToString(); |
| 772 remote_candidates_.erase(iter, remote_candidates_.end()); | 772 remote_candidates_.erase(iter, remote_candidates_.end()); |
| 773 } | 773 } |
| 774 } | 774 } |
| 775 | 775 |
| 776 // Creates connections from all of the ports that we care about to the given | 776 // Creates connections from all of the ports that we care about to the given |
| 777 // remote candidate. The return value is true if we created a connection from | 777 // remote candidate. The return value is true if we created a connection from |
| 778 // the origin port. | 778 // the origin port. |
| 779 bool P2PTransportChannel::CreateConnections(const Candidate& remote_candidate, | 779 bool P2PTransportChannel::CreateConnections(const Candidate& remote_candidate, |
| 780 PortInterface* origin_port) { | 780 PortInterface* origin_port) { |
| 781 ASSERT(worker_thread_ == rtc::Thread::Current()); | 781 ASSERT(network_thread_ == rtc::Thread::Current()); |
| 782 | 782 |
| 783 // If we've already seen the new remote candidate (in the current candidate | 783 // If we've already seen the new remote candidate (in the current candidate |
| 784 // generation), then we shouldn't try creating connections for it. | 784 // generation), then we shouldn't try creating connections for it. |
| 785 // We either already have a connection for it, or we previously created one | 785 // We either already have a connection for it, or we previously created one |
| 786 // and then later pruned it. If we don't return, the channel will again | 786 // and then later pruned it. If we don't return, the channel will again |
| 787 // re-create any connections that were previously pruned, which will then | 787 // re-create any connections that were previously pruned, which will then |
| 788 // immediately be re-pruned, churning the network for no purpose. | 788 // immediately be re-pruned, churning the network for no purpose. |
| 789 // This only applies to candidates received over signaling (i.e. origin_port | 789 // This only applies to candidates received over signaling (i.e. origin_port |
| 790 // is NULL). | 790 // is NULL). |
| 791 if (!origin_port && IsDuplicateRemoteCandidate(remote_candidate)) { | 791 if (!origin_port && IsDuplicateRemoteCandidate(remote_candidate)) { |
| (...skipping 128 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 920 return; | 920 return; |
| 921 } | 921 } |
| 922 | 922 |
| 923 // Try this candidate for all future ports. | 923 // Try this candidate for all future ports. |
| 924 remote_candidates_.push_back(RemoteCandidate(remote_candidate, origin_port)); | 924 remote_candidates_.push_back(RemoteCandidate(remote_candidate, origin_port)); |
| 925 } | 925 } |
| 926 | 926 |
| 927 // Set options on ourselves is simply setting options on all of our available | 927 // Set options on ourselves is simply setting options on all of our available |
| 928 // port objects. | 928 // port objects. |
| 929 int P2PTransportChannel::SetOption(rtc::Socket::Option opt, int value) { | 929 int P2PTransportChannel::SetOption(rtc::Socket::Option opt, int value) { |
| 930 ASSERT(worker_thread_ == rtc::Thread::Current()); | 930 ASSERT(network_thread_ == rtc::Thread::Current()); |
| 931 OptionMap::iterator it = options_.find(opt); | 931 OptionMap::iterator it = options_.find(opt); |
| 932 if (it == options_.end()) { | 932 if (it == options_.end()) { |
| 933 options_.insert(std::make_pair(opt, value)); | 933 options_.insert(std::make_pair(opt, value)); |
| 934 } else if (it->second == value) { | 934 } else if (it->second == value) { |
| 935 return 0; | 935 return 0; |
| 936 } else { | 936 } else { |
| 937 it->second = value; | 937 it->second = value; |
| 938 } | 938 } |
| 939 | 939 |
| 940 for (PortInterface* port : ports_) { | 940 for (PortInterface* port : ports_) { |
| 941 int val = port->SetOption(opt, value); | 941 int val = port->SetOption(opt, value); |
| 942 if (val < 0) { | 942 if (val < 0) { |
| 943 // Because this also occurs deferred, probably no point in reporting an | 943 // Because this also occurs deferred, probably no point in reporting an |
| 944 // error | 944 // error |
| 945 LOG(WARNING) << "SetOption(" << opt << ", " << value | 945 LOG(WARNING) << "SetOption(" << opt << ", " << value |
| 946 << ") failed: " << port->GetError(); | 946 << ") failed: " << port->GetError(); |
| 947 } | 947 } |
| 948 } | 948 } |
| 949 return 0; | 949 return 0; |
| 950 } | 950 } |
| 951 | 951 |
| 952 bool P2PTransportChannel::GetOption(rtc::Socket::Option opt, int* value) { | 952 bool P2PTransportChannel::GetOption(rtc::Socket::Option opt, int* value) { |
| 953 ASSERT(worker_thread_ == rtc::Thread::Current()); | 953 ASSERT(network_thread_ == rtc::Thread::Current()); |
| 954 | 954 |
| 955 const auto& found = options_.find(opt); | 955 const auto& found = options_.find(opt); |
| 956 if (found == options_.end()) { | 956 if (found == options_.end()) { |
| 957 return false; | 957 return false; |
| 958 } | 958 } |
| 959 *value = found->second; | 959 *value = found->second; |
| 960 return true; | 960 return true; |
| 961 } | 961 } |
| 962 | 962 |
| 963 // Send data to the other side, using our selected connection. | 963 // Send data to the other side, using our selected connection. |
| 964 int P2PTransportChannel::SendPacket(const char *data, size_t len, | 964 int P2PTransportChannel::SendPacket(const char *data, size_t len, |
| 965 const rtc::PacketOptions& options, | 965 const rtc::PacketOptions& options, |
| 966 int flags) { | 966 int flags) { |
| 967 ASSERT(worker_thread_ == rtc::Thread::Current()); | 967 ASSERT(network_thread_ == rtc::Thread::Current()); |
| 968 if (flags != 0) { | 968 if (flags != 0) { |
| 969 error_ = EINVAL; | 969 error_ = EINVAL; |
| 970 return -1; | 970 return -1; |
| 971 } | 971 } |
| 972 // If we don't think the connection is working yet, return ENOTCONN | 972 // If we don't think the connection is working yet, return ENOTCONN |
| 973 // instead of sending a packet that will probably be dropped. | 973 // instead of sending a packet that will probably be dropped. |
| 974 if (!ReadyToSend(selected_connection_)) { | 974 if (!ReadyToSend(selected_connection_)) { |
| 975 error_ = ENOTCONN; | 975 error_ = ENOTCONN; |
| 976 return -1; | 976 return -1; |
| 977 } | 977 } |
| 978 | 978 |
| 979 last_sent_packet_id_ = options.packet_id; | 979 last_sent_packet_id_ = options.packet_id; |
| 980 int sent = selected_connection_->Send(data, len, options); | 980 int sent = selected_connection_->Send(data, len, options); |
| 981 if (sent <= 0) { | 981 if (sent <= 0) { |
| 982 ASSERT(sent < 0); | 982 ASSERT(sent < 0); |
| 983 error_ = selected_connection_->GetError(); | 983 error_ = selected_connection_->GetError(); |
| 984 } | 984 } |
| 985 return sent; | 985 return sent; |
| 986 } | 986 } |
| 987 | 987 |
| 988 bool P2PTransportChannel::GetStats(ConnectionInfos *infos) { | 988 bool P2PTransportChannel::GetStats(ConnectionInfos *infos) { |
| 989 ASSERT(worker_thread_ == rtc::Thread::Current()); | 989 ASSERT(network_thread_ == rtc::Thread::Current()); |
| 990 // Gather connection infos. | 990 // Gather connection infos. |
| 991 infos->clear(); | 991 infos->clear(); |
| 992 | 992 |
| 993 for (Connection* connection : connections_) { | 993 for (Connection* connection : connections_) { |
| 994 ConnectionInfo info = connection->stats(); | 994 ConnectionInfo info = connection->stats(); |
| 995 info.best_connection = (selected_connection_ == connection); | 995 info.best_connection = (selected_connection_ == connection); |
| 996 info.receiving = connection->receiving(); | 996 info.receiving = connection->receiving(); |
| 997 info.writable = (connection->write_state() == Connection::STATE_WRITABLE); | 997 info.writable = (connection->write_state() == Connection::STATE_WRITABLE); |
| 998 info.timeout = | 998 info.timeout = |
| 999 (connection->write_state() == Connection::STATE_WRITE_TIMEOUT); | 999 (connection->write_state() == Connection::STATE_WRITE_TIMEOUT); |
| (...skipping 24 matching lines...) Expand all Loading... |
| 1024 // We need to copy the list of connections since some may delete themselves | 1024 // We need to copy the list of connections since some may delete themselves |
| 1025 // when we call UpdateState. | 1025 // when we call UpdateState. |
| 1026 for (Connection* c : connections_) { | 1026 for (Connection* c : connections_) { |
| 1027 c->UpdateState(now); | 1027 c->UpdateState(now); |
| 1028 } | 1028 } |
| 1029 } | 1029 } |
| 1030 | 1030 |
| 1031 // Prepare for best candidate sorting. | 1031 // Prepare for best candidate sorting. |
| 1032 void P2PTransportChannel::RequestSortAndStateUpdate() { | 1032 void P2PTransportChannel::RequestSortAndStateUpdate() { |
| 1033 if (!sort_dirty_) { | 1033 if (!sort_dirty_) { |
| 1034 worker_thread_->Post(RTC_FROM_HERE, this, MSG_SORT_AND_UPDATE_STATE); | 1034 network_thread_->Post(RTC_FROM_HERE, this, MSG_SORT_AND_UPDATE_STATE); |
| 1035 sort_dirty_ = true; | 1035 sort_dirty_ = true; |
| 1036 } | 1036 } |
| 1037 } | 1037 } |
| 1038 | 1038 |
| 1039 void P2PTransportChannel::MaybeStartPinging() { | 1039 void P2PTransportChannel::MaybeStartPinging() { |
| 1040 if (started_pinging_) { | 1040 if (started_pinging_) { |
| 1041 return; | 1041 return; |
| 1042 } | 1042 } |
| 1043 | 1043 |
| 1044 int64_t now = rtc::TimeMillis(); | 1044 int64_t now = rtc::TimeMillis(); |
| (...skipping 158 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1203 return (conn->write_state() == Connection::STATE_WRITE_INIT && | 1203 return (conn->write_state() == Connection::STATE_WRITE_INIT && |
| 1204 config_.presume_writable_when_fully_relayed && | 1204 config_.presume_writable_when_fully_relayed && |
| 1205 conn->local_candidate().type() == RELAY_PORT_TYPE && | 1205 conn->local_candidate().type() == RELAY_PORT_TYPE && |
| 1206 (conn->remote_candidate().type() == RELAY_PORT_TYPE || | 1206 (conn->remote_candidate().type() == RELAY_PORT_TYPE || |
| 1207 conn->remote_candidate().type() == PRFLX_PORT_TYPE)); | 1207 conn->remote_candidate().type() == PRFLX_PORT_TYPE)); |
| 1208 } | 1208 } |
| 1209 | 1209 |
| 1210 // Sort the available connections to find the best one. We also monitor | 1210 // Sort the available connections to find the best one. We also monitor |
| 1211 // the number of available connections and the current state. | 1211 // the number of available connections and the current state. |
| 1212 void P2PTransportChannel::SortConnectionsAndUpdateState() { | 1212 void P2PTransportChannel::SortConnectionsAndUpdateState() { |
| 1213 ASSERT(worker_thread_ == rtc::Thread::Current()); | 1213 ASSERT(network_thread_ == rtc::Thread::Current()); |
| 1214 | 1214 |
| 1215 // Make sure the connection states are up-to-date since this affects how they | 1215 // Make sure the connection states are up-to-date since this affects how they |
| 1216 // will be sorted. | 1216 // will be sorted. |
| 1217 UpdateConnectionStates(); | 1217 UpdateConnectionStates(); |
| 1218 | 1218 |
| 1219 // Any changes after this point will require a re-sort. | 1219 // Any changes after this point will require a re-sort. |
| 1220 sort_dirty_ = false; | 1220 sort_dirty_ = false; |
| 1221 | 1221 |
| 1222 // Find the best alternative connection by sorting. It is important to note | 1222 // Find the best alternative connection by sorting. It is important to note |
| 1223 // that amongst equal preference, writable connections, this will choose the | 1223 // that amongst equal preference, writable connections, this will choose the |
| (...skipping 463 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1687 default: | 1687 default: |
| 1688 RTC_DCHECK(false); | 1688 RTC_DCHECK(false); |
| 1689 return false; | 1689 return false; |
| 1690 } | 1690 } |
| 1691 } | 1691 } |
| 1692 | 1692 |
| 1693 // When a connection's state changes, we need to figure out who to use as | 1693 // When a connection's state changes, we need to figure out who to use as |
| 1694 // the selected connection again. It could have become usable, or become | 1694 // the selected connection again. It could have become usable, or become |
| 1695 // unusable. | 1695 // unusable. |
| 1696 void P2PTransportChannel::OnConnectionStateChange(Connection* connection) { | 1696 void P2PTransportChannel::OnConnectionStateChange(Connection* connection) { |
| 1697 ASSERT(worker_thread_ == rtc::Thread::Current()); | 1697 ASSERT(network_thread_ == rtc::Thread::Current()); |
| 1698 | 1698 |
| 1699 // May stop the allocator session when at least one connection becomes | 1699 // May stop the allocator session when at least one connection becomes |
| 1700 // strongly connected after starting to get ports and the local candidate of | 1700 // strongly connected after starting to get ports and the local candidate of |
| 1701 // the connection is at the latest generation. It is not enough to check | 1701 // the connection is at the latest generation. It is not enough to check |
| 1702 // that the connection becomes weakly connected because the connection may be | 1702 // that the connection becomes weakly connected because the connection may be |
| 1703 // changing from (writable, receiving) to (writable, not receiving). | 1703 // changing from (writable, receiving) to (writable, not receiving). |
| 1704 bool strongly_connected = !connection->weak(); | 1704 bool strongly_connected = !connection->weak(); |
| 1705 bool latest_generation = connection->local_candidate().generation() >= | 1705 bool latest_generation = connection->local_candidate().generation() >= |
| 1706 allocator_session()->generation(); | 1706 allocator_session()->generation(); |
| 1707 if (strongly_connected && latest_generation) { | 1707 if (strongly_connected && latest_generation) { |
| 1708 MaybeStopPortAllocatorSessions(); | 1708 MaybeStopPortAllocatorSessions(); |
| 1709 } | 1709 } |
| 1710 | 1710 |
| 1711 // We have to unroll the stack before doing this because we may be changing | 1711 // We have to unroll the stack before doing this because we may be changing |
| 1712 // the state of connections while sorting. | 1712 // the state of connections while sorting. |
| 1713 RequestSortAndStateUpdate(); | 1713 RequestSortAndStateUpdate(); |
| 1714 } | 1714 } |
| 1715 | 1715 |
| 1716 // When a connection is removed, edit it out, and then update our best | 1716 // When a connection is removed, edit it out, and then update our best |
| 1717 // connection. | 1717 // connection. |
| 1718 void P2PTransportChannel::OnConnectionDestroyed(Connection* connection) { | 1718 void P2PTransportChannel::OnConnectionDestroyed(Connection* connection) { |
| 1719 ASSERT(worker_thread_ == rtc::Thread::Current()); | 1719 ASSERT(network_thread_ == rtc::Thread::Current()); |
| 1720 | 1720 |
| 1721 // Note: the previous selected_connection_ may be destroyed by now, so don't | 1721 // Note: the previous selected_connection_ may be destroyed by now, so don't |
| 1722 // use it. | 1722 // use it. |
| 1723 | 1723 |
| 1724 // Remove this connection from the list. | 1724 // Remove this connection from the list. |
| 1725 std::vector<Connection*>::iterator iter = | 1725 std::vector<Connection*>::iterator iter = |
| 1726 std::find(connections_.begin(), connections_.end(), connection); | 1726 std::find(connections_.begin(), connections_.end(), connection); |
| 1727 ASSERT(iter != connections_.end()); | 1727 ASSERT(iter != connections_.end()); |
| 1728 pinged_connections_.erase(*iter); | 1728 pinged_connections_.erase(*iter); |
| 1729 unpinged_connections_.erase(*iter); | 1729 unpinged_connections_.erase(*iter); |
| (...skipping 16 matching lines...) Expand all Loading... |
| 1746 // If a non-selected connection was destroyed, we don't need to re-sort but | 1746 // If a non-selected connection was destroyed, we don't need to re-sort but |
| 1747 // we do need to update state, because we could be switching to "failed" or | 1747 // we do need to update state, because we could be switching to "failed" or |
| 1748 // "completed". | 1748 // "completed". |
| 1749 UpdateState(); | 1749 UpdateState(); |
| 1750 } | 1750 } |
| 1751 } | 1751 } |
| 1752 | 1752 |
| 1753 // When a port is destroyed, remove it from our list of ports to use for | 1753 // When a port is destroyed, remove it from our list of ports to use for |
| 1754 // connection attempts. | 1754 // connection attempts. |
| 1755 void P2PTransportChannel::OnPortDestroyed(PortInterface* port) { | 1755 void P2PTransportChannel::OnPortDestroyed(PortInterface* port) { |
| 1756 ASSERT(worker_thread_ == rtc::Thread::Current()); | 1756 ASSERT(network_thread_ == rtc::Thread::Current()); |
| 1757 | 1757 |
| 1758 ports_.erase(std::remove(ports_.begin(), ports_.end(), port), ports_.end()); | 1758 ports_.erase(std::remove(ports_.begin(), ports_.end(), port), ports_.end()); |
| 1759 pruned_ports_.erase( | 1759 pruned_ports_.erase( |
| 1760 std::remove(pruned_ports_.begin(), pruned_ports_.end(), port), | 1760 std::remove(pruned_ports_.begin(), pruned_ports_.end(), port), |
| 1761 pruned_ports_.end()); | 1761 pruned_ports_.end()); |
| 1762 LOG(INFO) << "Removed port because it is destroyed: " << ports_.size() | 1762 LOG(INFO) << "Removed port because it is destroyed: " << ports_.size() |
| 1763 << " remaining"; | 1763 << " remaining"; |
| 1764 } | 1764 } |
| 1765 | 1765 |
| 1766 void P2PTransportChannel::OnPortsPruned( | 1766 void P2PTransportChannel::OnPortsPruned( |
| 1767 PortAllocatorSession* session, | 1767 PortAllocatorSession* session, |
| 1768 const std::vector<PortInterface*>& ports) { | 1768 const std::vector<PortInterface*>& ports) { |
| 1769 ASSERT(worker_thread_ == rtc::Thread::Current()); | 1769 ASSERT(network_thread_ == rtc::Thread::Current()); |
| 1770 for (PortInterface* port : ports) { | 1770 for (PortInterface* port : ports) { |
| 1771 if (PrunePort(port)) { | 1771 if (PrunePort(port)) { |
| 1772 LOG(INFO) << "Removed port: " << port->ToString() << " " << ports_.size() | 1772 LOG(INFO) << "Removed port: " << port->ToString() << " " << ports_.size() |
| 1773 << " remaining"; | 1773 << " remaining"; |
| 1774 } | 1774 } |
| 1775 } | 1775 } |
| 1776 } | 1776 } |
| 1777 | 1777 |
| 1778 void P2PTransportChannel::OnCandidatesRemoved( | 1778 void P2PTransportChannel::OnCandidatesRemoved( |
| 1779 PortAllocatorSession* session, | 1779 PortAllocatorSession* session, |
| 1780 const std::vector<Candidate>& candidates) { | 1780 const std::vector<Candidate>& candidates) { |
| 1781 ASSERT(worker_thread_ == rtc::Thread::Current()); | 1781 ASSERT(network_thread_ == rtc::Thread::Current()); |
| 1782 // Do not signal candidate removals if continual gathering is not enabled, or | 1782 // Do not signal candidate removals if continual gathering is not enabled, or |
| 1783 // if this is not the last session because an ICE restart would have signaled | 1783 // if this is not the last session because an ICE restart would have signaled |
| 1784 // the remote side to remove all candidates in previous sessions. | 1784 // the remote side to remove all candidates in previous sessions. |
| 1785 if (!config_.gather_continually() || session != allocator_session()) { | 1785 if (!config_.gather_continually() || session != allocator_session()) { |
| 1786 return; | 1786 return; |
| 1787 } | 1787 } |
| 1788 | 1788 |
| 1789 std::vector<Candidate> candidates_to_remove; | 1789 std::vector<Candidate> candidates_to_remove; |
| 1790 for (Candidate candidate : candidates) { | 1790 for (Candidate candidate : candidates) { |
| 1791 candidate.set_transport_name(transport_name()); | 1791 candidate.set_transport_name(transport_name()); |
| (...skipping 29 matching lines...) Expand all Loading... |
| 1821 ports_.erase(it); | 1821 ports_.erase(it); |
| 1822 pruned_ports_.push_back(port); | 1822 pruned_ports_.push_back(port); |
| 1823 return true; | 1823 return true; |
| 1824 } | 1824 } |
| 1825 | 1825 |
| 1826 // We data is available, let listeners know | 1826 // We data is available, let listeners know |
| 1827 void P2PTransportChannel::OnReadPacket(Connection* connection, | 1827 void P2PTransportChannel::OnReadPacket(Connection* connection, |
| 1828 const char* data, | 1828 const char* data, |
| 1829 size_t len, | 1829 size_t len, |
| 1830 const rtc::PacketTime& packet_time) { | 1830 const rtc::PacketTime& packet_time) { |
| 1831 ASSERT(worker_thread_ == rtc::Thread::Current()); | 1831 ASSERT(network_thread_ == rtc::Thread::Current()); |
| 1832 | 1832 |
| 1833 // Do not deliver, if packet doesn't belong to the correct transport channel. | 1833 // Do not deliver, if packet doesn't belong to the correct transport channel. |
| 1834 if (!FindConnection(connection)) | 1834 if (!FindConnection(connection)) |
| 1835 return; | 1835 return; |
| 1836 | 1836 |
| 1837 // Let the client know of an incoming packet | 1837 // Let the client know of an incoming packet |
| 1838 SignalReadPacket(this, data, len, packet_time, 0); | 1838 SignalReadPacket(this, data, len, packet_time, 0); |
| 1839 | 1839 |
| 1840 // May need to switch the sending connection based on the receiving media path | 1840 // May need to switch the sending connection based on the receiving media path |
| 1841 // if this is the controlled side. | 1841 // if this is the controlled side. |
| 1842 if (ice_role_ == ICEROLE_CONTROLLED) { | 1842 if (ice_role_ == ICEROLE_CONTROLLED) { |
| 1843 MaybeSwitchSelectedConnection(connection, "data received"); | 1843 MaybeSwitchSelectedConnection(connection, "data received"); |
| 1844 } | 1844 } |
| 1845 } | 1845 } |
| 1846 | 1846 |
| 1847 void P2PTransportChannel::OnSentPacket(const rtc::SentPacket& sent_packet) { | 1847 void P2PTransportChannel::OnSentPacket(const rtc::SentPacket& sent_packet) { |
| 1848 ASSERT(worker_thread_ == rtc::Thread::Current()); | 1848 ASSERT(network_thread_ == rtc::Thread::Current()); |
| 1849 | 1849 |
| 1850 SignalSentPacket(this, sent_packet); | 1850 SignalSentPacket(this, sent_packet); |
| 1851 } | 1851 } |
| 1852 | 1852 |
| 1853 void P2PTransportChannel::OnReadyToSend(Connection* connection) { | 1853 void P2PTransportChannel::OnReadyToSend(Connection* connection) { |
| 1854 if (connection == selected_connection_ && writable()) { | 1854 if (connection == selected_connection_ && writable()) { |
| 1855 SignalReadyToSend(this); | 1855 SignalReadyToSend(this); |
| 1856 } | 1856 } |
| 1857 } | 1857 } |
| 1858 | 1858 |
| (...skipping 108 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1967 | 1967 |
| 1968 // During the initial state when nothing has been pinged yet, return the first | 1968 // During the initial state when nothing has been pinged yet, return the first |
| 1969 // one in the ordered |connections_|. | 1969 // one in the ordered |connections_|. |
| 1970 return *(std::find_if(connections_.begin(), connections_.end(), | 1970 return *(std::find_if(connections_.begin(), connections_.end(), |
| 1971 [conn1, conn2](Connection* conn) { | 1971 [conn1, conn2](Connection* conn) { |
| 1972 return conn == conn1 || conn == conn2; | 1972 return conn == conn1 || conn == conn2; |
| 1973 })); | 1973 })); |
| 1974 } | 1974 } |
| 1975 | 1975 |
| 1976 } // namespace cricket | 1976 } // namespace cricket |
| OLD | NEW |