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 248 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
938 void P2PTransportChannel::UpdateConnectionStates() { | 927 void P2PTransportChannel::UpdateConnectionStates() { |
939 int64_t now = rtc::TimeMillis(); | 928 int64_t now = rtc::TimeMillis(); |
940 | 929 |
941 // We need to copy the list of connections since some may delete themselves | 930 // We need to copy the list of connections since some may delete themselves |
942 // when we call UpdateState. | 931 // when we call UpdateState. |
943 for (size_t i = 0; i < connections_.size(); ++i) | 932 for (size_t i = 0; i < connections_.size(); ++i) |
944 connections_[i]->UpdateState(now); | 933 connections_[i]->UpdateState(now); |
945 } | 934 } |
946 | 935 |
947 // Prepare for best candidate sorting. | 936 // Prepare for best candidate sorting. |
948 void P2PTransportChannel::RequestSort() { | 937 void P2PTransportChannel::RequestSortAndStateUpdate() { |
949 if (!sort_dirty_) { | 938 if (!sort_dirty_) { |
950 worker_thread_->Post(RTC_FROM_HERE, this, MSG_SORT); | 939 worker_thread_->Post(RTC_FROM_HERE, this, MSG_SORT_AND_UPDATE_STATE); |
951 sort_dirty_ = true; | 940 sort_dirty_ = true; |
952 } | 941 } |
953 } | 942 } |
954 | 943 |
944 void P2PTransportChannel::MaybeStartPinging() { | |
945 if (started_pinging_) { | |
946 return; | |
947 } | |
948 LOG(LS_INFO) << "IN maybestartpinging"; | |
949 | |
950 int64_t now = rtc::TimeMillis(); | |
951 if (std::any_of( | |
952 connections_.begin(), connections_.end(), | |
953 [this, now](const Connection* c) { return IsPingable(c, now); })) { | |
954 LOG_J(LS_INFO, this) << "Have a pingable connection for the first time; " | |
955 << "starting to ping."; | |
956 thread()->Post(RTC_FROM_HERE, this, MSG_CHECK_AND_PING); | |
957 started_pinging_ = true; | |
958 } | |
959 } | |
960 | |
955 // Compare two connections based on their writing, receiving, and connected | 961 // Compare two connections based on their writing, receiving, and connected |
956 // states. | 962 // states. |
957 int P2PTransportChannel::CompareConnectionStates(const Connection* a, | 963 int P2PTransportChannel::CompareConnectionStates(const Connection* a, |
958 const Connection* b) const { | 964 const Connection* b) const { |
959 // First, prefer a connection that's writable or presumed writable over | 965 // First, prefer a connection that's writable or presumed writable over |
960 // one that's not writable. | 966 // one that's not writable. |
961 bool a_writable = a->writable() || PresumedWritable(a); | 967 bool a_writable = a->writable() || PresumedWritable(a); |
962 bool b_writable = b->writable() || PresumedWritable(b); | 968 bool b_writable = b->writable() || PresumedWritable(b); |
963 if (a_writable && !b_writable) { | 969 if (a_writable && !b_writable) { |
964 return a_is_better; | 970 return a_is_better; |
(...skipping 156 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1121 int prefs_cmp = CompareConnectionCandidates(selected, conn); | 1127 int prefs_cmp = CompareConnectionCandidates(selected, conn); |
1122 if (prefs_cmp != 0) { | 1128 if (prefs_cmp != 0) { |
1123 return prefs_cmp < 0; | 1129 return prefs_cmp < 0; |
1124 } | 1130 } |
1125 | 1131 |
1126 return selected->rtt() - conn->rtt() >= kMinImprovement; | 1132 return selected->rtt() - conn->rtt() >= kMinImprovement; |
1127 } | 1133 } |
1128 | 1134 |
1129 // Sort the available connections to find the best one. We also monitor | 1135 // Sort the available connections to find the best one. We also monitor |
1130 // the number of available connections and the current state. | 1136 // the number of available connections and the current state. |
1131 void P2PTransportChannel::SortConnections() { | 1137 void P2PTransportChannel::SortConnectionsAndUpdateState() { |
1132 ASSERT(worker_thread_ == rtc::Thread::Current()); | 1138 ASSERT(worker_thread_ == rtc::Thread::Current()); |
1133 | 1139 |
1134 // Make sure the connection states are up-to-date since this affects how they | 1140 // Make sure the connection states are up-to-date since this affects how they |
1135 // will be sorted. | 1141 // will be sorted. |
1136 UpdateConnectionStates(); | 1142 UpdateConnectionStates(); |
1137 | 1143 |
1138 // Any changes after this point will require a re-sort. | 1144 // Any changes after this point will require a re-sort. |
1139 sort_dirty_ = false; | 1145 sort_dirty_ = false; |
1140 | 1146 |
1141 // Find the best alternative connection by sorting. It is important to note | 1147 // 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... | |
1190 break; | 1196 break; |
1191 } | 1197 } |
1192 } | 1198 } |
1193 | 1199 |
1194 // Now update the writable state of the channel with the information we have | 1200 // Now update the writable state of the channel with the information we have |
1195 // so far. | 1201 // so far. |
1196 if (all_connections_timedout) { | 1202 if (all_connections_timedout) { |
1197 HandleAllTimedOut(); | 1203 HandleAllTimedOut(); |
1198 } | 1204 } |
1199 | 1205 |
1200 // Update the state of this channel. This method is called whenever the | 1206 // Update the state of this channel. |
1201 // state of any connection changes, so this is a good place to do this. | |
1202 UpdateState(); | 1207 UpdateState(); |
1208 | |
1209 // Also possibly start pinging. | |
1210 // We could start pinging if: | |
1211 // * The first connection was created. | |
1212 // * ICE credentials were provided. | |
1213 // * A TCP connection became connected. | |
pthatcher1
2016/06/29 17:45:43
Oh, wow, good catch about TCP. And much cleaner.
Taylor Brandstetter
2016/06/29 18:04:56
It actually wasn't my catch; it was the unit tests
| |
1214 MaybeStartPinging(); | |
1203 } | 1215 } |
1204 | 1216 |
1205 void P2PTransportChannel::PruneConnections() { | 1217 void P2PTransportChannel::PruneConnections() { |
1206 // We can prune any connection for which there is a connected, writable | 1218 // We can prune any connection for which there is a connected, writable |
1207 // connection on the same network with better or equal priority. We leave | 1219 // connection on the same network with better or equal priority. We leave |
1208 // those with better priority just in case they become writable later (at | 1220 // those with better priority just in case they become writable later (at |
1209 // which point, we would prune out the current selected connection). We leave | 1221 // which point, we would prune out the current selected connection). We leave |
1210 // connections on other networks because they may not be using the same | 1222 // connections on other networks because they may not be using the same |
1211 // resources and they may represent very distinct paths over which we can | 1223 // resources and they may represent very distinct paths over which we can |
1212 // switch. If the |premier| connection is not connected, we may be | 1224 // switch. If the |premier| connection is not connected, we may be |
(...skipping 50 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1263 } | 1275 } |
1264 SignalSelectedCandidatePairChanged(this, selected_connection_, | 1276 SignalSelectedCandidatePairChanged(this, selected_connection_, |
1265 last_sent_packet_id_); | 1277 last_sent_packet_id_); |
1266 } | 1278 } |
1267 | 1279 |
1268 // Warning: UpdateState should eventually be called whenever a connection | 1280 // Warning: UpdateState should eventually be called whenever a connection |
1269 // is added, deleted, or the write state of any connection changes so that the | 1281 // is added, deleted, or the write state of any connection changes so that the |
1270 // transport controller will get the up-to-date channel state. However it | 1282 // transport controller will get the up-to-date channel state. However it |
1271 // should not be called too often; in the case that multiple connection states | 1283 // should not be called too often; in the case that multiple connection states |
1272 // change, it should be called after all the connection states have changed. For | 1284 // change, it should be called after all the connection states have changed. For |
1273 // example, we call this at the end of SortConnections. | 1285 // example, we call this at the end of SortConnectionsAndUpdateState. |
1274 void P2PTransportChannel::UpdateState() { | 1286 void P2PTransportChannel::UpdateState() { |
1275 TransportChannelState state = ComputeState(); | 1287 TransportChannelState state = ComputeState(); |
1276 if (state_ != state) { | 1288 if (state_ != state) { |
1277 LOG_J(LS_INFO, this) << "Transport channel state changed from " << state_ | 1289 LOG_J(LS_INFO, this) << "Transport channel state changed from " << state_ |
1278 << " to " << state; | 1290 << " to " << state; |
1279 // Check that the requested transition is allowed. Note that | 1291 // Check that the requested transition is allowed. Note that |
1280 // P2PTransportChannel does not (yet) implement a direct mapping of the ICE | 1292 // P2PTransportChannel does not (yet) implement a direct mapping of the ICE |
1281 // states from the standard; the difference is covered by | 1293 // states from the standard; the difference is covered by |
1282 // TransportController and PeerConnection. | 1294 // TransportController and PeerConnection. |
1283 switch (state_) { | 1295 switch (state_) { |
(...skipping 88 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1372 return connections_[i]; | 1384 return connections_[i]; |
1373 } | 1385 } |
1374 } | 1386 } |
1375 | 1387 |
1376 return NULL; | 1388 return NULL; |
1377 } | 1389 } |
1378 | 1390 |
1379 // Handle any queued up requests | 1391 // Handle any queued up requests |
1380 void P2PTransportChannel::OnMessage(rtc::Message *pmsg) { | 1392 void P2PTransportChannel::OnMessage(rtc::Message *pmsg) { |
1381 switch (pmsg->message_id) { | 1393 switch (pmsg->message_id) { |
1382 case MSG_SORT: | 1394 case MSG_SORT_AND_UPDATE_STATE: |
1383 OnSort(); | 1395 SortConnectionsAndUpdateState(); |
1384 break; | 1396 break; |
1385 case MSG_CHECK_AND_PING: | 1397 case MSG_CHECK_AND_PING: |
1386 OnCheckAndPing(); | 1398 OnCheckAndPing(); |
1387 break; | 1399 break; |
1388 default: | 1400 default: |
1389 ASSERT(false); | 1401 ASSERT(false); |
1390 break; | 1402 break; |
1391 } | 1403 } |
1392 } | 1404 } |
1393 | 1405 |
1394 // Handle queued up sort request | |
1395 void P2PTransportChannel::OnSort() { | |
1396 // Resort the connections based on the new statistics. | |
1397 SortConnections(); | |
1398 } | |
1399 | |
1400 // Handle queued up check-and-ping request | 1406 // Handle queued up check-and-ping request |
1401 void P2PTransportChannel::OnCheckAndPing() { | 1407 void P2PTransportChannel::OnCheckAndPing() { |
1402 // Make sure the states of the connections are up-to-date (since this affects | 1408 // Make sure the states of the connections are up-to-date (since this affects |
1403 // which ones are pingable). | 1409 // which ones are pingable). |
1404 UpdateConnectionStates(); | 1410 UpdateConnectionStates(); |
1405 // When the selected connection is not receiving or not writable, or any | 1411 // When the selected connection is not receiving or not writable, or any |
1406 // active connection has not been pinged enough times, use the weak ping | 1412 // active connection has not been pinged enough times, use the weak ping |
1407 // interval. | 1413 // interval. |
1408 bool need_more_pings_at_weak_interval = std::any_of( | 1414 bool need_more_pings_at_weak_interval = std::any_of( |
1409 connections_.begin(), connections_.end(), [](Connection* conn) { | 1415 connections_.begin(), connections_.end(), [](Connection* conn) { |
1410 return conn->active() && | 1416 return conn->active() && |
1411 conn->num_pings_sent() < MIN_PINGS_AT_WEAK_PING_INTERVAL; | 1417 conn->num_pings_sent() < MIN_PINGS_AT_WEAK_PING_INTERVAL; |
1412 }); | 1418 }); |
1413 int ping_interval = (weak() || need_more_pings_at_weak_interval) | 1419 int ping_interval = (weak() || need_more_pings_at_weak_interval) |
1414 ? weak_ping_interval_ | 1420 ? weak_ping_interval_ |
1415 : STRONG_PING_INTERVAL; | 1421 : STRONG_PING_INTERVAL; |
1416 if (rtc::TimeMillis() >= last_ping_sent_ms_ + ping_interval) { | 1422 if (rtc::TimeMillis() >= last_ping_sent_ms_ + ping_interval) { |
1417 Connection* conn = FindNextPingableConnection(); | 1423 Connection* conn = FindNextPingableConnection(); |
1418 if (conn) { | 1424 if (conn) { |
1419 PingConnection(conn); | 1425 PingConnection(conn); |
1420 MarkConnectionPinged(conn); | 1426 MarkConnectionPinged(conn); |
1421 } | 1427 } |
1422 } | 1428 } |
1423 int delay = std::min(ping_interval, check_receiving_interval_); | 1429 int delay = std::min(ping_interval, check_receiving_interval_); |
1424 thread()->PostDelayed(RTC_FROM_HERE, delay, this, MSG_CHECK_AND_PING); | 1430 thread()->PostDelayed(RTC_FROM_HERE, delay, this, MSG_CHECK_AND_PING); |
1425 } | 1431 } |
1426 | 1432 |
1427 // A connection is considered a backup connection if the channel state | 1433 // A connection is considered a backup connection if the channel state |
1428 // is completed, the connection is not the selected connection and it is active. | 1434 // is completed, the connection is not the selected connection and it is active. |
1429 bool P2PTransportChannel::IsBackupConnection(Connection* conn) const { | 1435 bool P2PTransportChannel::IsBackupConnection(const Connection* conn) const { |
1430 return state_ == STATE_COMPLETED && conn != selected_connection_ && | 1436 return state_ == STATE_COMPLETED && conn != selected_connection_ && |
1431 conn->active(); | 1437 conn->active(); |
1432 } | 1438 } |
1433 | 1439 |
1434 // Is the connection in a state for us to even consider pinging the other side? | 1440 // Is the connection in a state for us to even consider pinging the other side? |
1435 // We consider a connection pingable even if it's not connected because that's | 1441 // We consider a connection pingable even if it's not connected because that's |
1436 // how a TCP connection is kicked into reconnecting on the active side. | 1442 // how a TCP connection is kicked into reconnecting on the active side. |
1437 bool P2PTransportChannel::IsPingable(Connection* conn, int64_t now) { | 1443 bool P2PTransportChannel::IsPingable(const Connection* conn, |
1444 int64_t now) const { | |
1438 const Candidate& remote = conn->remote_candidate(); | 1445 const Candidate& remote = conn->remote_candidate(); |
1439 // We should never get this far with an empty remote ufrag. | 1446 // We should never get this far with an empty remote ufrag. |
1440 ASSERT(!remote.username().empty()); | 1447 ASSERT(!remote.username().empty()); |
1441 if (remote.username().empty() || remote.password().empty()) { | 1448 if (remote.username().empty() || remote.password().empty()) { |
1442 // If we don't have an ICE ufrag and pwd, there's no way we can ping. | 1449 // If we don't have an ICE ufrag and pwd, there's no way we can ping. |
1443 return false; | 1450 return false; |
1444 } | 1451 } |
1445 | 1452 |
1446 // A failed connection will not be pinged. | 1453 // A failed connection will not be pinged. |
1447 if (conn->state() == Connection::STATE_FAILED) { | 1454 if (conn->state() == Connection::STATE_FAILED) { |
(...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1485 bool P2PTransportChannel::IsSelectedConnectionPingable(int64_t now) { | 1492 bool P2PTransportChannel::IsSelectedConnectionPingable(int64_t now) { |
1486 if (!selected_connection_ || !selected_connection_->connected() || | 1493 if (!selected_connection_ || !selected_connection_->connected() || |
1487 !selected_connection_->writable()) { | 1494 !selected_connection_->writable()) { |
1488 return false; | 1495 return false; |
1489 } | 1496 } |
1490 | 1497 |
1491 int interval = CalculateActiveWritablePingInterval(selected_connection_, now); | 1498 int interval = CalculateActiveWritablePingInterval(selected_connection_, now); |
1492 return selected_connection_->last_ping_sent() + interval <= now; | 1499 return selected_connection_->last_ping_sent() + interval <= now; |
1493 } | 1500 } |
1494 | 1501 |
1495 int P2PTransportChannel::CalculateActiveWritablePingInterval(Connection* conn, | 1502 int P2PTransportChannel::CalculateActiveWritablePingInterval( |
1496 int64_t now) { | 1503 const Connection* conn, |
1504 int64_t now) const { | |
1497 // Ping each connection at a higher rate at least | 1505 // Ping each connection at a higher rate at least |
1498 // MIN_PINGS_AT_WEAK_PING_INTERVAL times. | 1506 // MIN_PINGS_AT_WEAK_PING_INTERVAL times. |
1499 if (conn->num_pings_sent() < MIN_PINGS_AT_WEAK_PING_INTERVAL) { | 1507 if (conn->num_pings_sent() < MIN_PINGS_AT_WEAK_PING_INTERVAL) { |
1500 return weak_ping_interval_; | 1508 return weak_ping_interval_; |
1501 } | 1509 } |
1502 | 1510 |
1503 int stable_interval = config_.stable_writable_connection_ping_interval; | 1511 int stable_interval = config_.stable_writable_connection_ping_interval; |
1504 int stablizing_interval = | 1512 int stablizing_interval = |
1505 std::min(stable_interval, STABILIZING_WRITABLE_CONNECTION_PING_INTERVAL); | 1513 std::min(stable_interval, STABILIZING_WRITABLE_CONNECTION_PING_INTERVAL); |
1506 | 1514 |
(...skipping 64 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1571 // changing from (writable, receiving) to (writable, not receiving). | 1579 // changing from (writable, receiving) to (writable, not receiving). |
1572 bool strongly_connected = !connection->weak(); | 1580 bool strongly_connected = !connection->weak(); |
1573 bool latest_generation = connection->local_candidate().generation() >= | 1581 bool latest_generation = connection->local_candidate().generation() >= |
1574 allocator_session()->generation(); | 1582 allocator_session()->generation(); |
1575 if (strongly_connected && latest_generation) { | 1583 if (strongly_connected && latest_generation) { |
1576 MaybeStopPortAllocatorSessions(); | 1584 MaybeStopPortAllocatorSessions(); |
1577 } | 1585 } |
1578 | 1586 |
1579 // We have to unroll the stack before doing this because we may be changing | 1587 // We have to unroll the stack before doing this because we may be changing |
1580 // the state of connections while sorting. | 1588 // the state of connections while sorting. |
1581 RequestSort(); | 1589 RequestSortAndStateUpdate(); |
1582 } | 1590 } |
1583 | 1591 |
1584 // When a connection is removed, edit it out, and then update our best | 1592 // When a connection is removed, edit it out, and then update our best |
1585 // connection. | 1593 // connection. |
1586 void P2PTransportChannel::OnConnectionDestroyed(Connection* connection) { | 1594 void P2PTransportChannel::OnConnectionDestroyed(Connection* connection) { |
1587 ASSERT(worker_thread_ == rtc::Thread::Current()); | 1595 ASSERT(worker_thread_ == rtc::Thread::Current()); |
1588 | 1596 |
1589 // Note: the previous selected_connection_ may be destroyed by now, so don't | 1597 // Note: the previous selected_connection_ may be destroyed by now, so don't |
1590 // use it. | 1598 // use it. |
1591 | 1599 |
1592 // Remove this connection from the list. | 1600 // Remove this connection from the list. |
1593 std::vector<Connection*>::iterator iter = | 1601 std::vector<Connection*>::iterator iter = |
1594 std::find(connections_.begin(), connections_.end(), connection); | 1602 std::find(connections_.begin(), connections_.end(), connection); |
1595 ASSERT(iter != connections_.end()); | 1603 ASSERT(iter != connections_.end()); |
1596 pinged_connections_.erase(*iter); | 1604 pinged_connections_.erase(*iter); |
1597 unpinged_connections_.erase(*iter); | 1605 unpinged_connections_.erase(*iter); |
1598 connections_.erase(iter); | 1606 connections_.erase(iter); |
1599 | 1607 |
1600 LOG_J(LS_INFO, this) << "Removed connection (" | 1608 LOG_J(LS_INFO, this) << "Removed connection (" |
1601 << static_cast<int>(connections_.size()) << " remaining)"; | 1609 << static_cast<int>(connections_.size()) << " remaining)"; |
1602 | 1610 |
1603 // If this is currently the selected connection, then we need to pick a new | 1611 // If this is currently the selected connection, then we need to pick a new |
1604 // one. The call to SortConnections will pick a new one. It looks at the | 1612 // one. The call to SortConnectionsAndUpdateState will pick a new one. It |
1605 // current selected connection in order to avoid switching between fairly | 1613 // looks at the current selected connection in order to avoid switching |
1606 // similar ones. Since this connection is no longer an option, we can just | 1614 // between fairly similar ones. Since this connection is no longer an option, |
1607 // set selected to nullptr and re-choose a best assuming that there was no | 1615 // we can just set selected to nullptr and re-choose a best assuming that |
1608 // selected connection. | 1616 // there was no selected connection. |
1609 if (selected_connection_ == connection) { | 1617 if (selected_connection_ == connection) { |
1610 LOG(LS_INFO) << "selected connection destroyed. Will choose a new one."; | 1618 LOG(LS_INFO) << "selected connection destroyed. Will choose a new one."; |
1611 SwitchSelectedConnection(nullptr); | 1619 SwitchSelectedConnection(nullptr); |
1612 RequestSort(); | 1620 RequestSortAndStateUpdate(); |
1613 } | 1621 } |
pthatcher1
2016/06/29 17:45:43
Do we need to update the state even if the destroy
Taylor Brandstetter
2016/06/29 18:04:56
You're right; I didn't mean to delete that. But it
| |
1614 | |
1615 UpdateState(); | |
1616 } | 1622 } |
1617 | 1623 |
1618 // When a port is destroyed remove it from our list of ports to use for | 1624 // When a port is destroyed remove it from our list of ports to use for |
1619 // connection attempts. | 1625 // connection attempts. |
1620 void P2PTransportChannel::OnPortDestroyed(PortInterface* port) { | 1626 void P2PTransportChannel::OnPortDestroyed(PortInterface* port) { |
1621 ASSERT(worker_thread_ == rtc::Thread::Current()); | 1627 ASSERT(worker_thread_ == rtc::Thread::Current()); |
1622 | 1628 |
1623 // Remove this port from the lists (if we didn't drop it already). | 1629 // Remove this port from the lists (if we didn't drop it already). |
1624 ports_.erase(std::remove(ports_.begin(), ports_.end(), port), ports_.end()); | 1630 ports_.erase(std::remove(ports_.begin(), ports_.end(), port), ports_.end()); |
1625 removed_ports_.erase( | 1631 removed_ports_.erase( |
(...skipping 173 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1799 | 1805 |
1800 // During the initial state when nothing has been pinged yet, return the first | 1806 // During the initial state when nothing has been pinged yet, return the first |
1801 // one in the ordered |connections_|. | 1807 // one in the ordered |connections_|. |
1802 return *(std::find_if(connections_.begin(), connections_.end(), | 1808 return *(std::find_if(connections_.begin(), connections_.end(), |
1803 [conn1, conn2](Connection* conn) { | 1809 [conn1, conn2](Connection* conn) { |
1804 return conn == conn1 || conn == conn2; | 1810 return conn == conn1 || conn == conn2; |
1805 })); | 1811 })); |
1806 } | 1812 } |
1807 | 1813 |
1808 } // namespace cricket | 1814 } // namespace cricket |
OLD | NEW |