Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(80)

Side by Side Diff: webrtc/p2p/base/p2ptransportchannel.cc

Issue 2099563004: Start ICE connectivity checks as soon as the first pair is pingable. (Closed) Base URL: https://chromium.googlesource.com/external/webrtc.git@master
Patch Set: Removing debug log message, adding missing UpdateState. Created 4 years, 5 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « webrtc/p2p/base/p2ptransportchannel.h ('k') | webrtc/p2p/base/p2ptransportchannel_unittest.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
OLDNEW
« no previous file with comments | « webrtc/p2p/base/p2ptransportchannel.h ('k') | webrtc/p2p/base/p2ptransportchannel_unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698