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 |
11 #include "webrtc/p2p/base/p2ptransportchannel.h" | 11 #include "webrtc/p2p/base/p2ptransportchannel.h" |
12 | 12 |
13 #include <algorithm> | 13 #include <algorithm> |
14 #include <set> | 14 #include <set> |
15 | 15 |
16 #include "webrtc/base/common.h" | 16 #include "webrtc/base/common.h" |
17 #include "webrtc/base/crc32.h" | 17 #include "webrtc/base/crc32.h" |
18 #include "webrtc/base/logging.h" | 18 #include "webrtc/base/logging.h" |
19 #include "webrtc/base/stringencode.h" | 19 #include "webrtc/base/stringencode.h" |
20 #include "webrtc/p2p/base/candidate.h" | 20 #include "webrtc/p2p/base/candidate.h" |
21 #include "webrtc/p2p/base/candidatepairinterface.h" | 21 #include "webrtc/p2p/base/candidatepairinterface.h" |
22 #include "webrtc/p2p/base/common.h" | 22 #include "webrtc/p2p/base/common.h" |
23 #include "webrtc/p2p/base/relayport.h" // For RELAY_PORT_TYPE. | 23 #include "webrtc/p2p/base/relayport.h" // For RELAY_PORT_TYPE. |
24 #include "webrtc/p2p/base/stunport.h" // For STUN_PORT_TYPE. | 24 #include "webrtc/p2p/base/stunport.h" // For STUN_PORT_TYPE. |
25 #include "webrtc/system_wrappers/include/field_trial.h" | 25 #include "webrtc/system_wrappers/include/field_trial.h" |
26 | 26 |
27 namespace { | 27 namespace { |
28 | 28 |
29 // messages for queuing up work for ourselves | 29 // messages for queuing up work for ourselves |
30 enum { MSG_SORT = 1, MSG_CHECK_AND_PING }; | 30 enum { MSG_SORT_AND_UPDATE_STATE = 1, MSG_CHECK_AND_PING }; |
31 | 31 |
32 // The minimum improvement in RTT that justifies a switch. | 32 // The minimum improvement in RTT that justifies a switch. |
33 static const double kMinImprovement = 10; | 33 static const double kMinImprovement = 10; |
34 | 34 |
35 bool IsRelayRelay(const cricket::Connection* conn) { | 35 bool IsRelayRelay(const cricket::Connection* conn) { |
36 return conn->local_candidate().type() == cricket::RELAY_PORT_TYPE && | 36 return conn->local_candidate().type() == cricket::RELAY_PORT_TYPE && |
37 conn->remote_candidate().type() == cricket::RELAY_PORT_TYPE; | 37 conn->remote_candidate().type() == cricket::RELAY_PORT_TYPE; |
38 } | 38 } |
39 | 39 |
40 bool IsUdp(cricket::Connection* conn) { | 40 bool IsUdp(cricket::Connection* conn) { |
(...skipping 239 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
280 } | 280 } |
281 } | 281 } |
282 // We need to update the credentials and generation for any peer reflexive | 282 // We need to update the credentials and generation for any peer reflexive |
283 // candidates. | 283 // candidates. |
284 for (Connection* conn : connections_) { | 284 for (Connection* conn : connections_) { |
285 conn->MaybeSetRemoteIceCredentialsAndGeneration( | 285 conn->MaybeSetRemoteIceCredentialsAndGeneration( |
286 ice_ufrag, ice_pwd, | 286 ice_ufrag, ice_pwd, |
287 static_cast<int>(remote_ice_parameters_.size() - 1)); | 287 static_cast<int>(remote_ice_parameters_.size() - 1)); |
288 } | 288 } |
289 // Updating the remote ICE candidate generation could change the sort order. | 289 // Updating the remote ICE candidate generation could change the sort order. |
290 RequestSort(); | 290 RequestSortAndStateUpdate(); |
291 } | 291 } |
292 | 292 |
293 void P2PTransportChannel::SetRemoteIceMode(IceMode mode) { | 293 void P2PTransportChannel::SetRemoteIceMode(IceMode mode) { |
294 remote_ice_mode_ = mode; | 294 remote_ice_mode_ = mode; |
295 } | 295 } |
296 | 296 |
297 void P2PTransportChannel::SetIceConfig(const IceConfig& config) { | 297 void P2PTransportChannel::SetIceConfig(const IceConfig& config) { |
298 config_.gather_continually = config.gather_continually; | 298 config_.gather_continually = config.gather_continually; |
299 LOG(LS_INFO) << "Set gather_continually to " << config_.gather_continually; | 299 LOG(LS_INFO) << "Set gather_continually to " << config_.gather_continually; |
300 | 300 |
(...skipping 44 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
345 LOG(LS_INFO) << "Set presume writable when fully relayed to " | 345 LOG(LS_INFO) << "Set presume writable when fully relayed to " |
346 << config_.presume_writable_when_fully_relayed; | 346 << config_.presume_writable_when_fully_relayed; |
347 } | 347 } |
348 } | 348 } |
349 } | 349 } |
350 | 350 |
351 const IceConfig& P2PTransportChannel::config() const { | 351 const IceConfig& P2PTransportChannel::config() const { |
352 return config_; | 352 return config_; |
353 } | 353 } |
354 | 354 |
355 // Go into the state of processing candidates, and running in general | 355 void P2PTransportChannel::MaybeStartGathering() { |
356 void P2PTransportChannel::Connect() { | |
357 ASSERT(worker_thread_ == rtc::Thread::Current()); | |
358 if (ice_ufrag_.empty() || ice_pwd_.empty()) { | 356 if (ice_ufrag_.empty() || ice_pwd_.empty()) { |
359 ASSERT(false); | |
360 LOG(LS_ERROR) << "P2PTransportChannel::Connect: The ice_ufrag_ and the " | |
361 << "ice_pwd_ are not set."; | |
362 return; | 357 return; |
363 } | 358 } |
364 | |
365 // Start checking and pinging as the ports come in. | |
366 thread()->Post(RTC_FROM_HERE, this, MSG_CHECK_AND_PING); | |
367 } | |
368 | |
369 void P2PTransportChannel::MaybeStartGathering() { | |
370 // Start gathering if we never started before, or if an ICE restart occurred. | 359 // Start gathering if we never started before, or if an ICE restart occurred. |
371 if (allocator_sessions_.empty() || | 360 if (allocator_sessions_.empty() || |
372 IceCredentialsChanged(allocator_sessions_.back()->ice_ufrag(), | 361 IceCredentialsChanged(allocator_sessions_.back()->ice_ufrag(), |
373 allocator_sessions_.back()->ice_pwd(), ice_ufrag_, | 362 allocator_sessions_.back()->ice_pwd(), ice_ufrag_, |
374 ice_pwd_)) { | 363 ice_pwd_)) { |
375 if (gathering_state_ != kIceGatheringGathering) { | 364 if (gathering_state_ != kIceGatheringGathering) { |
376 gathering_state_ = kIceGatheringGathering; | 365 gathering_state_ = kIceGatheringGathering; |
377 SignalGatheringState(this); | 366 SignalGatheringState(this); |
378 } | 367 } |
379 // Time for a new allocator. | 368 // Time for a new allocator. |
(...skipping 56 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
436 | 425 |
437 // Attempt to create a connection from this new port to all of the remote | 426 // Attempt to create a connection from this new port to all of the remote |
438 // candidates that we were given so far. | 427 // candidates that we were given so far. |
439 | 428 |
440 std::vector<RemoteCandidate>::iterator iter; | 429 std::vector<RemoteCandidate>::iterator iter; |
441 for (iter = remote_candidates_.begin(); iter != remote_candidates_.end(); | 430 for (iter = remote_candidates_.begin(); iter != remote_candidates_.end(); |
442 ++iter) { | 431 ++iter) { |
443 CreateConnection(port, *iter, iter->origin_port()); | 432 CreateConnection(port, *iter, iter->origin_port()); |
444 } | 433 } |
445 | 434 |
446 SortConnections(); | 435 SortConnectionsAndUpdateState(); |
447 } | 436 } |
448 | 437 |
449 // A new candidate is available, let listeners know | 438 // A new candidate is available, let listeners know |
450 void P2PTransportChannel::OnCandidatesReady( | 439 void P2PTransportChannel::OnCandidatesReady( |
451 PortAllocatorSession* session, | 440 PortAllocatorSession* session, |
452 const std::vector<Candidate>& candidates) { | 441 const std::vector<Candidate>& candidates) { |
453 ASSERT(worker_thread_ == rtc::Thread::Current()); | 442 ASSERT(worker_thread_ == rtc::Thread::Current()); |
454 for (size_t i = 0; i < candidates.size(); ++i) { | 443 for (size_t i = 0; i < candidates.size(); ++i) { |
455 SignalCandidateGathered(this, candidates[i]); | 444 SignalCandidateGathered(this, candidates[i]); |
456 } | 445 } |
(...skipping 121 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
578 | 567 |
579 LOG(LS_INFO) << "Adding connection from " | 568 LOG(LS_INFO) << "Adding connection from " |
580 << (remote_candidate_is_new ? "peer reflexive" : "resurrected") | 569 << (remote_candidate_is_new ? "peer reflexive" : "resurrected") |
581 << " candidate: " << remote_candidate.ToString(); | 570 << " candidate: " << remote_candidate.ToString(); |
582 AddConnection(connection); | 571 AddConnection(connection); |
583 connection->HandleBindingRequest(stun_msg); | 572 connection->HandleBindingRequest(stun_msg); |
584 | 573 |
585 // Update the list of connections since we just added another. We do this | 574 // Update the list of connections since we just added another. We do this |
586 // after sending the response since it could (in principle) delete the | 575 // after sending the response since it could (in principle) delete the |
587 // connection in question. | 576 // connection in question. |
588 SortConnections(); | 577 SortConnectionsAndUpdateState(); |
589 } | 578 } |
590 | 579 |
591 void P2PTransportChannel::OnRoleConflict(PortInterface* port) { | 580 void P2PTransportChannel::OnRoleConflict(PortInterface* port) { |
592 SignalRoleConflict(this); // STUN ping will be sent when SetRole is called | 581 SignalRoleConflict(this); // STUN ping will be sent when SetRole is called |
593 // from Transport. | 582 // from Transport. |
594 } | 583 } |
595 | 584 |
596 const IceParameters* P2PTransportChannel::FindRemoteIceFromUfrag( | 585 const IceParameters* P2PTransportChannel::FindRemoteIceFromUfrag( |
597 const std::string& ufrag, | 586 const std::string& ufrag, |
598 uint32_t* generation) { | 587 uint32_t* generation) { |
(...skipping 23 matching lines...) Expand all Loading... |
622 << conn->ToString(); | 611 << conn->ToString(); |
623 return; | 612 return; |
624 } | 613 } |
625 | 614 |
626 LOG(LS_INFO) | 615 LOG(LS_INFO) |
627 << "Switching selected connection on controlled side due to nomination: " | 616 << "Switching selected connection on controlled side due to nomination: " |
628 << conn->ToString(); | 617 << conn->ToString(); |
629 SwitchSelectedConnection(conn); | 618 SwitchSelectedConnection(conn); |
630 // Now that we have selected a connection, it is time to prune other | 619 // Now that we have selected a connection, it is time to prune other |
631 // connections and update the read/write state of the channel. | 620 // connections and update the read/write state of the channel. |
632 RequestSort(); | 621 RequestSortAndStateUpdate(); |
633 } | 622 } |
634 | 623 |
635 void P2PTransportChannel::AddRemoteCandidate(const Candidate& candidate) { | 624 void P2PTransportChannel::AddRemoteCandidate(const Candidate& candidate) { |
636 ASSERT(worker_thread_ == rtc::Thread::Current()); | 625 ASSERT(worker_thread_ == rtc::Thread::Current()); |
637 | 626 |
638 uint32_t generation = GetRemoteCandidateGeneration(candidate); | 627 uint32_t generation = GetRemoteCandidateGeneration(candidate); |
639 // If a remote candidate with a previous generation arrives, drop it. | 628 // If a remote candidate with a previous generation arrives, drop it. |
640 if (generation < remote_ice_generation()) { | 629 if (generation < remote_ice_generation()) { |
641 LOG(LS_WARNING) << "Dropping a remote candidate because its ufrag " | 630 LOG(LS_WARNING) << "Dropping a remote candidate because its ufrag " |
642 << candidate.username() | 631 << candidate.username() |
(...skipping 26 matching lines...) Expand all Loading... |
669 // If this candidate matches what was thought to be a peer reflexive | 658 // If this candidate matches what was thought to be a peer reflexive |
670 // candidate, we need to update the candidate priority/etc. | 659 // candidate, we need to update the candidate priority/etc. |
671 for (Connection* conn : connections_) { | 660 for (Connection* conn : connections_) { |
672 conn->MaybeUpdatePeerReflexiveCandidate(new_remote_candidate); | 661 conn->MaybeUpdatePeerReflexiveCandidate(new_remote_candidate); |
673 } | 662 } |
674 | 663 |
675 // Create connections to this remote candidate. | 664 // Create connections to this remote candidate. |
676 CreateConnections(new_remote_candidate, NULL); | 665 CreateConnections(new_remote_candidate, NULL); |
677 | 666 |
678 // Resort the connections list, which may have new elements. | 667 // Resort the connections list, which may have new elements. |
679 SortConnections(); | 668 SortConnectionsAndUpdateState(); |
680 } | 669 } |
681 | 670 |
682 void P2PTransportChannel::RemoveRemoteCandidate( | 671 void P2PTransportChannel::RemoveRemoteCandidate( |
683 const Candidate& cand_to_remove) { | 672 const Candidate& cand_to_remove) { |
684 auto iter = | 673 auto iter = |
685 std::remove_if(remote_candidates_.begin(), remote_candidates_.end(), | 674 std::remove_if(remote_candidates_.begin(), remote_candidates_.end(), |
686 [cand_to_remove](const Candidate& candidate) { | 675 [cand_to_remove](const Candidate& candidate) { |
687 return cand_to_remove.MatchesForRemoval(candidate); | 676 return cand_to_remove.MatchesForRemoval(candidate); |
688 }); | 677 }); |
689 if (iter != remote_candidates_.end()) { | 678 if (iter != remote_candidates_.end()) { |
(...skipping 245 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
935 } | 924 } |
936 return static_cast<rtc::DiffServCodePoint> (it->second); | 925 return static_cast<rtc::DiffServCodePoint> (it->second); |
937 } | 926 } |
938 | 927 |
939 // Monitor connection states. | 928 // Monitor connection states. |
940 void P2PTransportChannel::UpdateConnectionStates() { | 929 void P2PTransportChannel::UpdateConnectionStates() { |
941 int64_t now = rtc::TimeMillis(); | 930 int64_t now = rtc::TimeMillis(); |
942 | 931 |
943 // We need to copy the list of connections since some may delete themselves | 932 // We need to copy the list of connections since some may delete themselves |
944 // when we call UpdateState. | 933 // when we call UpdateState. |
945 for (size_t i = 0; i < connections_.size(); ++i) | 934 for (Connection* c : connections_) { |
946 connections_[i]->UpdateState(now); | 935 c->UpdateState(now); |
| 936 } |
947 } | 937 } |
948 | 938 |
949 // Prepare for best candidate sorting. | 939 // Prepare for best candidate sorting. |
950 void P2PTransportChannel::RequestSort() { | 940 void P2PTransportChannel::RequestSortAndStateUpdate() { |
951 if (!sort_dirty_) { | 941 if (!sort_dirty_) { |
952 worker_thread_->Post(RTC_FROM_HERE, this, MSG_SORT); | 942 worker_thread_->Post(RTC_FROM_HERE, this, MSG_SORT_AND_UPDATE_STATE); |
953 sort_dirty_ = true; | 943 sort_dirty_ = true; |
954 } | 944 } |
955 } | 945 } |
956 | 946 |
| 947 void P2PTransportChannel::MaybeStartPinging() { |
| 948 if (started_pinging_) { |
| 949 return; |
| 950 } |
| 951 |
| 952 int64_t now = rtc::TimeMillis(); |
| 953 if (std::any_of( |
| 954 connections_.begin(), connections_.end(), |
| 955 [this, now](const Connection* c) { return IsPingable(c, now); })) { |
| 956 LOG_J(LS_INFO, this) << "Have a pingable connection for the first time; " |
| 957 << "starting to ping."; |
| 958 thread()->Post(RTC_FROM_HERE, this, MSG_CHECK_AND_PING); |
| 959 started_pinging_ = true; |
| 960 } |
| 961 } |
| 962 |
957 // Compare two connections based on their writing, receiving, and connected | 963 // Compare two connections based on their writing, receiving, and connected |
958 // states. | 964 // states. |
959 int P2PTransportChannel::CompareConnectionStates(const Connection* a, | 965 int P2PTransportChannel::CompareConnectionStates(const Connection* a, |
960 const Connection* b) const { | 966 const Connection* b) const { |
961 // First, prefer a connection that's writable or presumed writable over | 967 // First, prefer a connection that's writable or presumed writable over |
962 // one that's not writable. | 968 // one that's not writable. |
963 bool a_writable = a->writable() || PresumedWritable(a); | 969 bool a_writable = a->writable() || PresumedWritable(a); |
964 bool b_writable = b->writable() || PresumedWritable(b); | 970 bool b_writable = b->writable() || PresumedWritable(b); |
965 if (a_writable && !b_writable) { | 971 if (a_writable && !b_writable) { |
966 return a_is_better; | 972 return a_is_better; |
(...skipping 122 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1089 bool P2PTransportChannel::PresumedWritable(const Connection* conn) const { | 1095 bool P2PTransportChannel::PresumedWritable(const Connection* conn) const { |
1090 return (conn->write_state() == Connection::STATE_WRITE_INIT && | 1096 return (conn->write_state() == Connection::STATE_WRITE_INIT && |
1091 config_.presume_writable_when_fully_relayed && | 1097 config_.presume_writable_when_fully_relayed && |
1092 conn->local_candidate().type() == RELAY_PORT_TYPE && | 1098 conn->local_candidate().type() == RELAY_PORT_TYPE && |
1093 (conn->remote_candidate().type() == RELAY_PORT_TYPE || | 1099 (conn->remote_candidate().type() == RELAY_PORT_TYPE || |
1094 conn->remote_candidate().type() == PRFLX_PORT_TYPE)); | 1100 conn->remote_candidate().type() == PRFLX_PORT_TYPE)); |
1095 } | 1101 } |
1096 | 1102 |
1097 // Sort the available connections to find the best one. We also monitor | 1103 // Sort the available connections to find the best one. We also monitor |
1098 // the number of available connections and the current state. | 1104 // the number of available connections and the current state. |
1099 void P2PTransportChannel::SortConnections() { | 1105 void P2PTransportChannel::SortConnectionsAndUpdateState() { |
1100 ASSERT(worker_thread_ == rtc::Thread::Current()); | 1106 ASSERT(worker_thread_ == rtc::Thread::Current()); |
1101 | 1107 |
1102 // Make sure the connection states are up-to-date since this affects how they | 1108 // Make sure the connection states are up-to-date since this affects how they |
1103 // will be sorted. | 1109 // will be sorted. |
1104 UpdateConnectionStates(); | 1110 UpdateConnectionStates(); |
1105 | 1111 |
1106 // Any changes after this point will require a re-sort. | 1112 // Any changes after this point will require a re-sort. |
1107 sort_dirty_ = false; | 1113 sort_dirty_ = false; |
1108 | 1114 |
1109 // Find the best alternative connection by sorting. It is important to note | 1115 // Find the best alternative connection by sorting. It is important to note |
(...skipping 48 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1158 break; | 1164 break; |
1159 } | 1165 } |
1160 } | 1166 } |
1161 | 1167 |
1162 // Now update the writable state of the channel with the information we have | 1168 // Now update the writable state of the channel with the information we have |
1163 // so far. | 1169 // so far. |
1164 if (all_connections_timedout) { | 1170 if (all_connections_timedout) { |
1165 HandleAllTimedOut(); | 1171 HandleAllTimedOut(); |
1166 } | 1172 } |
1167 | 1173 |
1168 // Update the state of this channel. This method is called whenever the | 1174 // Update the state of this channel. |
1169 // state of any connection changes, so this is a good place to do this. | |
1170 UpdateState(); | 1175 UpdateState(); |
| 1176 |
| 1177 // Also possibly start pinging. |
| 1178 // We could start pinging if: |
| 1179 // * The first connection was created. |
| 1180 // * ICE credentials were provided. |
| 1181 // * A TCP connection became connected. |
| 1182 MaybeStartPinging(); |
1171 } | 1183 } |
1172 | 1184 |
1173 void P2PTransportChannel::PruneConnections() { | 1185 void P2PTransportChannel::PruneConnections() { |
1174 // We can prune any connection for which there is a connected, writable | 1186 // We can prune any connection for which there is a connected, writable |
1175 // connection on the same network with better or equal priority. We leave | 1187 // connection on the same network with better or equal priority. We leave |
1176 // those with better priority just in case they become writable later (at | 1188 // those with better priority just in case they become writable later (at |
1177 // which point, we would prune out the current selected connection). We leave | 1189 // which point, we would prune out the current selected connection). We leave |
1178 // connections on other networks because they may not be using the same | 1190 // connections on other networks because they may not be using the same |
1179 // resources and they may represent very distinct paths over which we can | 1191 // resources and they may represent very distinct paths over which we can |
1180 // switch. If the |premier| connection is not connected, we may be | 1192 // switch. If the |premier| connection is not connected, we may be |
(...skipping 50 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1231 } | 1243 } |
1232 SignalSelectedCandidatePairChanged(this, selected_connection_, | 1244 SignalSelectedCandidatePairChanged(this, selected_connection_, |
1233 last_sent_packet_id_, ReadyToSend()); | 1245 last_sent_packet_id_, ReadyToSend()); |
1234 } | 1246 } |
1235 | 1247 |
1236 // Warning: UpdateState should eventually be called whenever a connection | 1248 // Warning: UpdateState should eventually be called whenever a connection |
1237 // is added, deleted, or the write state of any connection changes so that the | 1249 // is added, deleted, or the write state of any connection changes so that the |
1238 // transport controller will get the up-to-date channel state. However it | 1250 // transport controller will get the up-to-date channel state. However it |
1239 // should not be called too often; in the case that multiple connection states | 1251 // should not be called too often; in the case that multiple connection states |
1240 // change, it should be called after all the connection states have changed. For | 1252 // change, it should be called after all the connection states have changed. For |
1241 // example, we call this at the end of SortConnections. | 1253 // example, we call this at the end of SortConnectionsAndUpdateState. |
1242 void P2PTransportChannel::UpdateState() { | 1254 void P2PTransportChannel::UpdateState() { |
1243 TransportChannelState state = ComputeState(); | 1255 TransportChannelState state = ComputeState(); |
1244 if (state_ != state) { | 1256 if (state_ != state) { |
1245 LOG_J(LS_INFO, this) << "Transport channel state changed from " << state_ | 1257 LOG_J(LS_INFO, this) << "Transport channel state changed from " << state_ |
1246 << " to " << state; | 1258 << " to " << state; |
1247 // Check that the requested transition is allowed. Note that | 1259 // Check that the requested transition is allowed. Note that |
1248 // P2PTransportChannel does not (yet) implement a direct mapping of the ICE | 1260 // P2PTransportChannel does not (yet) implement a direct mapping of the ICE |
1249 // states from the standard; the difference is covered by | 1261 // states from the standard; the difference is covered by |
1250 // TransportController and PeerConnection. | 1262 // TransportController and PeerConnection. |
1251 switch (state_) { | 1263 switch (state_) { |
(...skipping 99 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1351 return connections_[i]; | 1363 return connections_[i]; |
1352 } | 1364 } |
1353 } | 1365 } |
1354 | 1366 |
1355 return NULL; | 1367 return NULL; |
1356 } | 1368 } |
1357 | 1369 |
1358 // Handle any queued up requests | 1370 // Handle any queued up requests |
1359 void P2PTransportChannel::OnMessage(rtc::Message *pmsg) { | 1371 void P2PTransportChannel::OnMessage(rtc::Message *pmsg) { |
1360 switch (pmsg->message_id) { | 1372 switch (pmsg->message_id) { |
1361 case MSG_SORT: | 1373 case MSG_SORT_AND_UPDATE_STATE: |
1362 OnSort(); | 1374 SortConnectionsAndUpdateState(); |
1363 break; | 1375 break; |
1364 case MSG_CHECK_AND_PING: | 1376 case MSG_CHECK_AND_PING: |
1365 OnCheckAndPing(); | 1377 OnCheckAndPing(); |
1366 break; | 1378 break; |
1367 default: | 1379 default: |
1368 ASSERT(false); | 1380 ASSERT(false); |
1369 break; | 1381 break; |
1370 } | 1382 } |
1371 } | 1383 } |
1372 | 1384 |
1373 // Handle queued up sort request | |
1374 void P2PTransportChannel::OnSort() { | |
1375 // Resort the connections based on the new statistics. | |
1376 SortConnections(); | |
1377 } | |
1378 | |
1379 // Handle queued up check-and-ping request | 1385 // Handle queued up check-and-ping request |
1380 void P2PTransportChannel::OnCheckAndPing() { | 1386 void P2PTransportChannel::OnCheckAndPing() { |
1381 // Make sure the states of the connections are up-to-date (since this affects | 1387 // Make sure the states of the connections are up-to-date (since this affects |
1382 // which ones are pingable). | 1388 // which ones are pingable). |
1383 UpdateConnectionStates(); | 1389 UpdateConnectionStates(); |
1384 // When the selected connection is not receiving or not writable, or any | 1390 // When the selected connection is not receiving or not writable, or any |
1385 // active connection has not been pinged enough times, use the weak ping | 1391 // active connection has not been pinged enough times, use the weak ping |
1386 // interval. | 1392 // interval. |
1387 bool need_more_pings_at_weak_interval = std::any_of( | 1393 bool need_more_pings_at_weak_interval = std::any_of( |
1388 connections_.begin(), connections_.end(), [](Connection* conn) { | 1394 connections_.begin(), connections_.end(), [](Connection* conn) { |
1389 return conn->active() && | 1395 return conn->active() && |
1390 conn->num_pings_sent() < MIN_PINGS_AT_WEAK_PING_INTERVAL; | 1396 conn->num_pings_sent() < MIN_PINGS_AT_WEAK_PING_INTERVAL; |
1391 }); | 1397 }); |
1392 int ping_interval = (weak() || need_more_pings_at_weak_interval) | 1398 int ping_interval = (weak() || need_more_pings_at_weak_interval) |
1393 ? weak_ping_interval_ | 1399 ? weak_ping_interval_ |
1394 : STRONG_PING_INTERVAL; | 1400 : STRONG_PING_INTERVAL; |
1395 if (rtc::TimeMillis() >= last_ping_sent_ms_ + ping_interval) { | 1401 if (rtc::TimeMillis() >= last_ping_sent_ms_ + ping_interval) { |
1396 Connection* conn = FindNextPingableConnection(); | 1402 Connection* conn = FindNextPingableConnection(); |
1397 if (conn) { | 1403 if (conn) { |
1398 PingConnection(conn); | 1404 PingConnection(conn); |
1399 MarkConnectionPinged(conn); | 1405 MarkConnectionPinged(conn); |
1400 } | 1406 } |
1401 } | 1407 } |
1402 int delay = std::min(ping_interval, check_receiving_interval_); | 1408 int delay = std::min(ping_interval, check_receiving_interval_); |
1403 thread()->PostDelayed(RTC_FROM_HERE, delay, this, MSG_CHECK_AND_PING); | 1409 thread()->PostDelayed(RTC_FROM_HERE, delay, this, MSG_CHECK_AND_PING); |
1404 } | 1410 } |
1405 | 1411 |
1406 // A connection is considered a backup connection if the channel state | 1412 // A connection is considered a backup connection if the channel state |
1407 // is completed, the connection is not the selected connection and it is active. | 1413 // is completed, the connection is not the selected connection and it is active. |
1408 bool P2PTransportChannel::IsBackupConnection(Connection* conn) const { | 1414 bool P2PTransportChannel::IsBackupConnection(const Connection* conn) const { |
1409 return state_ == STATE_COMPLETED && conn != selected_connection_ && | 1415 return state_ == STATE_COMPLETED && conn != selected_connection_ && |
1410 conn->active(); | 1416 conn->active(); |
1411 } | 1417 } |
1412 | 1418 |
1413 // Is the connection in a state for us to even consider pinging the other side? | 1419 // Is the connection in a state for us to even consider pinging the other side? |
1414 // We consider a connection pingable even if it's not connected because that's | 1420 // We consider a connection pingable even if it's not connected because that's |
1415 // how a TCP connection is kicked into reconnecting on the active side. | 1421 // how a TCP connection is kicked into reconnecting on the active side. |
1416 bool P2PTransportChannel::IsPingable(Connection* conn, int64_t now) { | 1422 bool P2PTransportChannel::IsPingable(const Connection* conn, |
| 1423 int64_t now) const { |
1417 const Candidate& remote = conn->remote_candidate(); | 1424 const Candidate& remote = conn->remote_candidate(); |
1418 // We should never get this far with an empty remote ufrag. | 1425 // We should never get this far with an empty remote ufrag. |
1419 ASSERT(!remote.username().empty()); | 1426 ASSERT(!remote.username().empty()); |
1420 if (remote.username().empty() || remote.password().empty()) { | 1427 if (remote.username().empty() || remote.password().empty()) { |
1421 // If we don't have an ICE ufrag and pwd, there's no way we can ping. | 1428 // If we don't have an ICE ufrag and pwd, there's no way we can ping. |
1422 return false; | 1429 return false; |
1423 } | 1430 } |
1424 | 1431 |
1425 // A failed connection will not be pinged. | 1432 // A failed connection will not be pinged. |
1426 if (conn->state() == Connection::STATE_FAILED) { | 1433 if (conn->state() == Connection::STATE_FAILED) { |
(...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1464 bool P2PTransportChannel::IsSelectedConnectionPingable(int64_t now) { | 1471 bool P2PTransportChannel::IsSelectedConnectionPingable(int64_t now) { |
1465 if (!selected_connection_ || !selected_connection_->connected() || | 1472 if (!selected_connection_ || !selected_connection_->connected() || |
1466 !selected_connection_->writable()) { | 1473 !selected_connection_->writable()) { |
1467 return false; | 1474 return false; |
1468 } | 1475 } |
1469 | 1476 |
1470 int interval = CalculateActiveWritablePingInterval(selected_connection_, now); | 1477 int interval = CalculateActiveWritablePingInterval(selected_connection_, now); |
1471 return selected_connection_->last_ping_sent() + interval <= now; | 1478 return selected_connection_->last_ping_sent() + interval <= now; |
1472 } | 1479 } |
1473 | 1480 |
1474 int P2PTransportChannel::CalculateActiveWritablePingInterval(Connection* conn, | 1481 int P2PTransportChannel::CalculateActiveWritablePingInterval( |
1475 int64_t now) { | 1482 const Connection* conn, |
| 1483 int64_t now) const { |
1476 // Ping each connection at a higher rate at least | 1484 // Ping each connection at a higher rate at least |
1477 // MIN_PINGS_AT_WEAK_PING_INTERVAL times. | 1485 // MIN_PINGS_AT_WEAK_PING_INTERVAL times. |
1478 if (conn->num_pings_sent() < MIN_PINGS_AT_WEAK_PING_INTERVAL) { | 1486 if (conn->num_pings_sent() < MIN_PINGS_AT_WEAK_PING_INTERVAL) { |
1479 return weak_ping_interval_; | 1487 return weak_ping_interval_; |
1480 } | 1488 } |
1481 | 1489 |
1482 int stable_interval = config_.stable_writable_connection_ping_interval; | 1490 int stable_interval = config_.stable_writable_connection_ping_interval; |
1483 int stablizing_interval = | 1491 int stablizing_interval = |
1484 std::min(stable_interval, STABILIZING_WRITABLE_CONNECTION_PING_INTERVAL); | 1492 std::min(stable_interval, STABILIZING_WRITABLE_CONNECTION_PING_INTERVAL); |
1485 | 1493 |
(...skipping 64 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1550 // changing from (writable, receiving) to (writable, not receiving). | 1558 // changing from (writable, receiving) to (writable, not receiving). |
1551 bool strongly_connected = !connection->weak(); | 1559 bool strongly_connected = !connection->weak(); |
1552 bool latest_generation = connection->local_candidate().generation() >= | 1560 bool latest_generation = connection->local_candidate().generation() >= |
1553 allocator_session()->generation(); | 1561 allocator_session()->generation(); |
1554 if (strongly_connected && latest_generation) { | 1562 if (strongly_connected && latest_generation) { |
1555 MaybeStopPortAllocatorSessions(); | 1563 MaybeStopPortAllocatorSessions(); |
1556 } | 1564 } |
1557 | 1565 |
1558 // We have to unroll the stack before doing this because we may be changing | 1566 // We have to unroll the stack before doing this because we may be changing |
1559 // the state of connections while sorting. | 1567 // the state of connections while sorting. |
1560 RequestSort(); | 1568 RequestSortAndStateUpdate(); |
1561 } | 1569 } |
1562 | 1570 |
1563 // When a connection is removed, edit it out, and then update our best | 1571 // When a connection is removed, edit it out, and then update our best |
1564 // connection. | 1572 // connection. |
1565 void P2PTransportChannel::OnConnectionDestroyed(Connection* connection) { | 1573 void P2PTransportChannel::OnConnectionDestroyed(Connection* connection) { |
1566 ASSERT(worker_thread_ == rtc::Thread::Current()); | 1574 ASSERT(worker_thread_ == rtc::Thread::Current()); |
1567 | 1575 |
1568 // Note: the previous selected_connection_ may be destroyed by now, so don't | 1576 // Note: the previous selected_connection_ may be destroyed by now, so don't |
1569 // use it. | 1577 // use it. |
1570 | 1578 |
1571 // Remove this connection from the list. | 1579 // Remove this connection from the list. |
1572 std::vector<Connection*>::iterator iter = | 1580 std::vector<Connection*>::iterator iter = |
1573 std::find(connections_.begin(), connections_.end(), connection); | 1581 std::find(connections_.begin(), connections_.end(), connection); |
1574 ASSERT(iter != connections_.end()); | 1582 ASSERT(iter != connections_.end()); |
1575 pinged_connections_.erase(*iter); | 1583 pinged_connections_.erase(*iter); |
1576 unpinged_connections_.erase(*iter); | 1584 unpinged_connections_.erase(*iter); |
1577 connections_.erase(iter); | 1585 connections_.erase(iter); |
1578 | 1586 |
1579 LOG_J(LS_INFO, this) << "Removed connection (" | 1587 LOG_J(LS_INFO, this) << "Removed connection (" |
1580 << static_cast<int>(connections_.size()) << " remaining)"; | 1588 << static_cast<int>(connections_.size()) << " remaining)"; |
1581 | 1589 |
1582 // If this is currently the selected connection, then we need to pick a new | 1590 // If this is currently the selected connection, then we need to pick a new |
1583 // one. The call to SortConnections will pick a new one. It looks at the | 1591 // one. The call to SortConnectionsAndUpdateState will pick a new one. It |
1584 // current selected connection in order to avoid switching between fairly | 1592 // looks at the current selected connection in order to avoid switching |
1585 // similar ones. Since this connection is no longer an option, we can just | 1593 // between fairly similar ones. Since this connection is no longer an option, |
1586 // set selected to nullptr and re-choose a best assuming that there was no | 1594 // we can just set selected to nullptr and re-choose a best assuming that |
1587 // selected connection. | 1595 // there was no selected connection. |
1588 if (selected_connection_ == connection) { | 1596 if (selected_connection_ == connection) { |
1589 LOG(LS_INFO) << "selected connection destroyed. Will choose a new one."; | 1597 LOG(LS_INFO) << "selected connection destroyed. Will choose a new one."; |
1590 SwitchSelectedConnection(nullptr); | 1598 SwitchSelectedConnection(nullptr); |
1591 RequestSort(); | 1599 RequestSortAndStateUpdate(); |
| 1600 } else { |
| 1601 // If a non-selected connection was destroyed, we don't need to re-sort but |
| 1602 // we do need to update state, because we could be switching to "failed" or |
| 1603 // "completed". |
| 1604 UpdateState(); |
1592 } | 1605 } |
1593 | |
1594 UpdateState(); | |
1595 } | 1606 } |
1596 | 1607 |
1597 // When a port is destroyed remove it from our list of ports to use for | 1608 // When a port is destroyed remove it from our list of ports to use for |
1598 // connection attempts. | 1609 // connection attempts. |
1599 void P2PTransportChannel::OnPortDestroyed(PortInterface* port) { | 1610 void P2PTransportChannel::OnPortDestroyed(PortInterface* port) { |
1600 ASSERT(worker_thread_ == rtc::Thread::Current()); | 1611 ASSERT(worker_thread_ == rtc::Thread::Current()); |
1601 | 1612 |
1602 // Remove this port from the lists (if we didn't drop it already). | 1613 // Remove this port from the lists (if we didn't drop it already). |
1603 ports_.erase(std::remove(ports_.begin(), ports_.end(), port), ports_.end()); | 1614 ports_.erase(std::remove(ports_.begin(), ports_.end(), port), ports_.end()); |
1604 removed_ports_.erase( | 1615 removed_ports_.erase( |
(...skipping 173 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1778 | 1789 |
1779 // During the initial state when nothing has been pinged yet, return the first | 1790 // During the initial state when nothing has been pinged yet, return the first |
1780 // one in the ordered |connections_|. | 1791 // one in the ordered |connections_|. |
1781 return *(std::find_if(connections_.begin(), connections_.end(), | 1792 return *(std::find_if(connections_.begin(), connections_.end(), |
1782 [conn1, conn2](Connection* conn) { | 1793 [conn1, conn2](Connection* conn) { |
1783 return conn == conn1 || conn == conn2; | 1794 return conn == conn1 || conn == conn2; |
1784 })); | 1795 })); |
1785 } | 1796 } |
1786 | 1797 |
1787 } // namespace cricket | 1798 } // namespace cricket |
OLD | NEW |