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

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

Issue 2143653005: Dampening connection switch. (Closed) Base URL: https://chromium.googlesource.com/external/webrtc@master
Patch Set: Fix some comments 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
(...skipping 62 matching lines...) Expand 10 before | Expand all | Expand 10 after
73 const int WEAK_PING_INTERVAL = 1000 * PING_PACKET_SIZE / 10000; 73 const int WEAK_PING_INTERVAL = 1000 * PING_PACKET_SIZE / 10000;
74 74
75 // Writable connections are pinged at a faster rate while stabilizing. 75 // Writable connections are pinged at a faster rate while stabilizing.
76 const int STABILIZING_WRITABLE_CONNECTION_PING_INTERVAL = 900; // ms 76 const int STABILIZING_WRITABLE_CONNECTION_PING_INTERVAL = 900; // ms
77 77
78 // Writable connections are pinged at a slower rate once stabilized. 78 // Writable connections are pinged at a slower rate once stabilized.
79 const int STABLE_WRITABLE_CONNECTION_PING_INTERVAL = 2500; // ms 79 const int STABLE_WRITABLE_CONNECTION_PING_INTERVAL = 2500; // ms
80 80
81 static const int MIN_CHECK_RECEIVING_INTERVAL = 50; // ms 81 static const int MIN_CHECK_RECEIVING_INTERVAL = 50; // ms
82 82
83 static const int RECEIVING_DAMPENING_INTERVAL = 500; // ms
pthatcher1 2016/07/13 21:17:23 I think we should be conservative with the value f
honghaiz3 2016/07/14 04:54:20 There is actually some risk of choosing the same d
84
83 // We periodically check if any existing networks do not have any connection 85 // We periodically check if any existing networks do not have any connection
84 // and regather on those networks. 86 // and regather on those networks.
85 static const int DEFAULT_REGATHER_ON_FAILED_NETWORKS_INTERVAL = 5 * 60 * 1000; 87 static const int DEFAULT_REGATHER_ON_FAILED_NETWORKS_INTERVAL = 5 * 60 * 1000;
86 static constexpr int a_is_better = 1; 88 static constexpr int a_is_better = 1;
87 static constexpr int b_is_better = -1; 89 static constexpr int b_is_better = -1;
88 90
89 P2PTransportChannel::P2PTransportChannel(const std::string& transport_name, 91 P2PTransportChannel::P2PTransportChannel(const std::string& transport_name,
90 int component, 92 int component,
91 P2PTransport* transport, 93 P2PTransport* transport,
92 PortAllocator* allocator) 94 PortAllocator* allocator)
(...skipping 12 matching lines...) Expand all
105 ice_role_(ICEROLE_UNKNOWN), 107 ice_role_(ICEROLE_UNKNOWN),
106 tiebreaker_(0), 108 tiebreaker_(0),
107 gathering_state_(kIceGatheringNew), 109 gathering_state_(kIceGatheringNew),
108 check_receiving_interval_(MIN_CHECK_RECEIVING_INTERVAL * 5), 110 check_receiving_interval_(MIN_CHECK_RECEIVING_INTERVAL * 5),
109 config_(MIN_CHECK_RECEIVING_INTERVAL * 50 /* receiving_timeout */, 111 config_(MIN_CHECK_RECEIVING_INTERVAL * 50 /* receiving_timeout */,
110 0 /* backup_connection_ping_interval */, 112 0 /* backup_connection_ping_interval */,
111 GATHER_ONCE /* continual_gathering_policy */, 113 GATHER_ONCE /* continual_gathering_policy */,
112 false /* prioritize_most_likely_candidate_pairs */, 114 false /* prioritize_most_likely_candidate_pairs */,
113 STABLE_WRITABLE_CONNECTION_PING_INTERVAL, 115 STABLE_WRITABLE_CONNECTION_PING_INTERVAL,
114 true /* presume_writable_when_fully_relayed */, 116 true /* presume_writable_when_fully_relayed */,
115 DEFAULT_REGATHER_ON_FAILED_NETWORKS_INTERVAL) { 117 DEFAULT_REGATHER_ON_FAILED_NETWORKS_INTERVAL,
118 RECEIVING_DAMPENING_INTERVAL) {
116 uint32_t weak_ping_interval = ::strtoul( 119 uint32_t weak_ping_interval = ::strtoul(
117 webrtc::field_trial::FindFullName("WebRTC-StunInterPacketDelay").c_str(), 120 webrtc::field_trial::FindFullName("WebRTC-StunInterPacketDelay").c_str(),
118 nullptr, 10); 121 nullptr, 10);
119 if (weak_ping_interval) { 122 if (weak_ping_interval) {
120 weak_ping_interval_ = static_cast<int>(weak_ping_interval); 123 weak_ping_interval_ = static_cast<int>(weak_ping_interval);
121 } 124 }
122 } 125 }
123 126
124 P2PTransportChannel::~P2PTransportChannel() { 127 P2PTransportChannel::~P2PTransportChannel() {
125 ASSERT(worker_thread_ == rtc::Thread::Current()); 128 ASSERT(worker_thread_ == rtc::Thread::Current());
(...skipping 51 matching lines...) Expand 10 before | Expand all | Expand 10 after
177 // criteria is as follows: 180 // criteria is as follows:
178 // i) write/receiving/connected states 181 // i) write/receiving/connected states
179 // ii) For controlled side, 182 // ii) For controlled side,
180 // a) nomination state, 183 // a) nomination state,
181 // b) last data received time. 184 // b) last data received time.
182 // iii) Lower cost / higher priority. 185 // iii) Lower cost / higher priority.
183 // iv) rtt. 186 // iv) rtt.
184 // TODO(honghaiz): Stop the aggressive nomination on the controlling side and 187 // TODO(honghaiz): Stop the aggressive nomination on the controlling side and
185 // implement the ice-renomination option. 188 // implement the ice-renomination option.
186 bool P2PTransportChannel::ShouldSwitchSelectedConnection( 189 bool P2PTransportChannel::ShouldSwitchSelectedConnection(
187 Connection* new_connection) const { 190 Connection* new_connection) {
188 if (!new_connection || selected_connection_ == new_connection) { 191 if (!new_connection || selected_connection_ == new_connection) {
189 return false; 192 return false;
190 } 193 }
191 194
192 if (selected_connection_ == nullptr) { 195 if (selected_connection_ == nullptr) {
193 return true; 196 return true;
194 } 197 }
195 198
196 int cmp = CompareConnections(selected_connection_, new_connection); 199 bool connection_dampened = false;
200 int cmp = CompareConnectionStatesWithDampening(
201 selected_connection_, new_connection, &connection_dampened);
197 if (cmp != 0) { 202 if (cmp != 0) {
198 return cmp < 0; 203 return cmp < 0;
199 } 204 }
205 // A connection is dampened indicates that it is in a better receiving state,
206 // so we need to remember it and check it again periodically.
207 if (connection_dampened) {
208 pending_selected_connection_ = new_connection;
209 }
pthatcher1 2016/07/13 21:17:23 I don't like the idea of ShouldSwitchSelectedConne
honghaiz3 2016/07/14 04:54:20 Done for other parts except that ShouldSwitchSelec
pthatcher1 2016/07/14 18:01:44 Can't the *caller* of ShouldSwitchSelectedConnecti
210
211 cmp = CompareConnectionsWithoutStates(selected_connection_, new_connection);
pthatcher1 2016/07/13 21:17:23 I also think it would be more simple to keep it as
honghaiz3 2016/07/14 04:54:21 Done.
212 if (cmp != 0) {
213 return cmp < 0;
214 }
200 215
201 // If everything else is the same, switch only if rtt has improved by 216 // If everything else is the same, switch only if rtt has improved by
202 // a margin. 217 // a margin.
203 return new_connection->rtt() <= selected_connection_->rtt() - kMinImprovement; 218 return new_connection->rtt() <= selected_connection_->rtt() - kMinImprovement;
204 } 219 }
205 220
206 void P2PTransportChannel::SetIceRole(IceRole ice_role) { 221 void P2PTransportChannel::SetIceRole(IceRole ice_role) {
207 ASSERT(worker_thread_ == rtc::Thread::Current()); 222 ASSERT(worker_thread_ == rtc::Thread::Current());
208 if (ice_role_ != ice_role) { 223 if (ice_role_ != ice_role) {
209 ice_role_ = ice_role; 224 ice_role_ = ice_role;
(...skipping 152 matching lines...) Expand 10 before | Expand all | Expand 10 after
362 << config_.presume_writable_when_fully_relayed; 377 << config_.presume_writable_when_fully_relayed;
363 } 378 }
364 } 379 }
365 380
366 if (config.regather_on_failed_networks_interval) { 381 if (config.regather_on_failed_networks_interval) {
367 config_.regather_on_failed_networks_interval = 382 config_.regather_on_failed_networks_interval =
368 config.regather_on_failed_networks_interval; 383 config.regather_on_failed_networks_interval;
369 LOG(LS_INFO) << "Set regather_on_failed_networks_interval to " 384 LOG(LS_INFO) << "Set regather_on_failed_networks_interval to "
370 << *config_.regather_on_failed_networks_interval; 385 << *config_.regather_on_failed_networks_interval;
371 } 386 }
387 if (config.receiving_dampening_interval) {
388 config_.receiving_dampening_interval = config.receiving_dampening_interval;
389 LOG(LS_INFO) << "Set receiving_dampening_interval to"
390 << *config_.receiving_dampening_interval;
391 }
372 } 392 }
373 393
374 const IceConfig& P2PTransportChannel::config() const { 394 const IceConfig& P2PTransportChannel::config() const {
375 return config_; 395 return config_;
376 } 396 }
377 397
378 void P2PTransportChannel::MaybeStartGathering() { 398 void P2PTransportChannel::MaybeStartGathering() {
379 if (ice_ufrag_.empty() || ice_pwd_.empty()) { 399 if (ice_ufrag_.empty() || ice_pwd_.empty()) {
380 return; 400 return;
381 } 401 }
(...skipping 246 matching lines...) Expand 10 before | Expand all | Expand 10 after
628 } 648 }
629 649
630 if (!ShouldSwitchSelectedConnection(conn)) { 650 if (!ShouldSwitchSelectedConnection(conn)) {
631 LOG(LS_INFO) 651 LOG(LS_INFO)
632 << "Not switching the selected connection on controlled side yet: " 652 << "Not switching the selected connection on controlled side yet: "
633 << conn->ToString(); 653 << conn->ToString();
634 return; 654 return;
635 } 655 }
636 656
637 LOG(LS_INFO) 657 LOG(LS_INFO)
638 << "Switching selected connection on controlled side due to nomination: " 658 << "Switching selected connection on controlled side due to nomination.";
639 << conn->ToString();
640 SwitchSelectedConnection(conn); 659 SwitchSelectedConnection(conn);
641 // Now that we have selected a connection, it is time to prune other 660 // Now that we have selected a connection, it is time to prune other
642 // connections and update the read/write state of the channel. 661 // connections and update the read/write state of the channel.
643 RequestSortAndStateUpdate(); 662 RequestSortAndStateUpdate();
644 } 663 }
645 664
646 void P2PTransportChannel::AddRemoteCandidate(const Candidate& candidate) { 665 void P2PTransportChannel::AddRemoteCandidate(const Candidate& candidate) {
647 ASSERT(worker_thread_ == rtc::Thread::Current()); 666 ASSERT(worker_thread_ == rtc::Thread::Current());
648 667
649 uint32_t generation = GetRemoteCandidateGeneration(candidate); 668 uint32_t generation = GetRemoteCandidateGeneration(candidate);
(...skipping 299 matching lines...) Expand 10 before | Expand all | Expand 10 after
949 968
950 // Monitor connection states. 969 // Monitor connection states.
951 void P2PTransportChannel::UpdateConnectionStates() { 970 void P2PTransportChannel::UpdateConnectionStates() {
952 int64_t now = rtc::TimeMillis(); 971 int64_t now = rtc::TimeMillis();
953 972
954 // We need to copy the list of connections since some may delete themselves 973 // We need to copy the list of connections since some may delete themselves
955 // when we call UpdateState. 974 // when we call UpdateState.
956 for (Connection* c : connections_) { 975 for (Connection* c : connections_) {
957 c->UpdateState(now); 976 c->UpdateState(now);
958 } 977 }
978
979 if (!selected_connection_) {
980 was_strong_ = false;
981 return;
982 }
983 bool is_strong = !selected_connection_->weak();
984 if (was_strong_ && !is_strong) {
985 // If the selected connection just changes to weak, reset the number of
986 // pings sent on the selected connection so that it will be pinged at least
987 // a few times.
988 selected_connection_->reset_num_pings_sent();
989 for (Connection* c : connections_) {
990 c->reset_first_received_since_channel_weak();
991 }
992 }
993 was_strong_ = is_strong;
pthatcher1 2016/07/13 21:17:23 I think we can calculate the "has it been receivin
honghaiz3 2016/07/14 04:54:21 We can do that. But a potential problem is that if
959 } 994 }
960 995
961 // Prepare for best candidate sorting. 996 // Prepare for best candidate sorting.
962 void P2PTransportChannel::RequestSortAndStateUpdate() { 997 void P2PTransportChannel::RequestSortAndStateUpdate() {
963 if (!sort_dirty_) { 998 if (!sort_dirty_) {
964 worker_thread_->Post(RTC_FROM_HERE, this, MSG_SORT_AND_UPDATE_STATE); 999 worker_thread_->Post(RTC_FROM_HERE, this, MSG_SORT_AND_UPDATE_STATE);
965 sort_dirty_ = true; 1000 sort_dirty_ = true;
966 } 1001 }
967 } 1002 }
968 1003
969 void P2PTransportChannel::MaybeStartPinging() { 1004 void P2PTransportChannel::MaybeStartPinging() {
970 if (started_pinging_) { 1005 if (started_pinging_) {
971 return; 1006 return;
972 } 1007 }
973 1008
974 int64_t now = rtc::TimeMillis(); 1009 int64_t now = rtc::TimeMillis();
975 if (std::any_of( 1010 if (std::any_of(
976 connections_.begin(), connections_.end(), 1011 connections_.begin(), connections_.end(),
977 [this, now](const Connection* c) { return IsPingable(c, now); })) { 1012 [this, now](const Connection* c) { return IsPingable(c, now); })) {
978 LOG_J(LS_INFO, this) << "Have a pingable connection for the first time; " 1013 LOG_J(LS_INFO, this) << "Have a pingable connection for the first time; "
979 << "starting to ping."; 1014 << "starting to ping.";
980 thread()->Post(RTC_FROM_HERE, this, MSG_CHECK_AND_PING); 1015 thread()->Post(RTC_FROM_HERE, this, MSG_CHECK_AND_PING);
981 thread()->PostDelayed(RTC_FROM_HERE, 1016 thread()->PostDelayed(RTC_FROM_HERE,
982 *config_.regather_on_failed_networks_interval, this, 1017 *config_.regather_on_failed_networks_interval, this,
983 MSG_REGATHER_ON_FAILED_NETWORKS); 1018 MSG_REGATHER_ON_FAILED_NETWORKS);
984 started_pinging_ = true; 1019 started_pinging_ = true;
985 } 1020 }
986 } 1021 }
987 1022
988 // Compare two connections based on their writing, receiving, and connected 1023 int P2PTransportChannel::CompareConnectionWriteAndConnectedStates(
989 // states. 1024 const Connection* a,
990 int P2PTransportChannel::CompareConnectionStates(const Connection* a, 1025 const Connection* b) const {
991 const Connection* b) const {
992 // First, prefer a connection that's writable or presumed writable over 1026 // First, prefer a connection that's writable or presumed writable over
993 // one that's not writable. 1027 // one that's not writable.
994 bool a_writable = a->writable() || PresumedWritable(a); 1028 bool a_writable = a->writable() || PresumedWritable(a);
995 bool b_writable = b->writable() || PresumedWritable(b); 1029 bool b_writable = b->writable() || PresumedWritable(b);
996 if (a_writable && !b_writable) { 1030 if (a_writable && !b_writable) {
997 return a_is_better; 1031 return a_is_better;
998 } 1032 }
999 if (!a_writable && b_writable) { 1033 if (!a_writable && b_writable) {
1000 return b_is_better; 1034 return b_is_better;
1001 } 1035 }
1002 1036
1003 // Sort based on write-state. Better states have lower values. 1037 // Better write-states have lower values, and a negative return value
1004 if (a->write_state() < b->write_state()) { 1038 // indicates b is better.
1005 return a_is_better; 1039 int cmp = b->write_state() - a->write_state();
1006 } 1040 if (cmp != 0) {
1007 if (b->write_state() < a->write_state()) { 1041 return cmp;
1008 return b_is_better;
1009 }
1010
1011 // We prefer a receiving connection to a non-receiving, higher-priority
1012 // connection when sorting connections and choosing which connection to
1013 // switch to.
1014 if (a->receiving() && !b->receiving()) {
1015 return a_is_better;
1016 }
1017 if (!a->receiving() && b->receiving()) {
1018 return b_is_better;
1019 } 1042 }
1020 1043
1021 // WARNING: Some complexity here about TCP reconnecting. 1044 // WARNING: Some complexity here about TCP reconnecting.
1022 // When a TCP connection fails because of a TCP socket disconnecting, the 1045 // When a TCP connection fails because of a TCP socket disconnecting, the
1023 // active side of the connection will attempt to reconnect for 5 seconds while 1046 // active side of the connection will attempt to reconnect for 5 seconds while
1024 // pretending to be writable (the connection is not set to the unwritable 1047 // pretending to be writable (the connection is not set to the unwritable
1025 // state). On the passive side, the connection also remains writable even 1048 // state). On the passive side, the connection also remains writable even
1026 // though it is disconnected, and a new connection is created when the active 1049 // though it is disconnected, and a new connection is created when the active
1027 // side connects. At that point, there are two TCP connections on the passive 1050 // side connects. At that point, there are two TCP connections on the passive
1028 // side: 1. the old, disconnected one that is pretending to be writable, and 1051 // side: 1. the old, disconnected one that is pretending to be writable, and
(...skipping 16 matching lines...) Expand all
1045 if (a->connected() && !b->connected()) { 1068 if (a->connected() && !b->connected()) {
1046 return a_is_better; 1069 return a_is_better;
1047 } 1070 }
1048 if (!a->connected() && b->connected()) { 1071 if (!a->connected() && b->connected()) {
1049 return b_is_better; 1072 return b_is_better;
1050 } 1073 }
1051 } 1074 }
1052 return 0; 1075 return 0;
1053 } 1076 }
1054 1077
1078 // Compare two connections based on their writing, connected, and receiving
1079 // states.
1080 int P2PTransportChannel::CompareConnectionStates(const Connection* a,
1081 const Connection* b) const {
1082 int cmp = CompareConnectionWriteAndConnectedStates(a, b);
1083 if (cmp != 0) {
1084 return cmp;
1085 }
1086
1087 // We prefer a receiving connection to a non-receiving, higher-priority
1088 // connection when sorting connections.
1089 if (a->receiving() && !b->receiving()) {
1090 return a_is_better;
1091 }
1092 if (!a->receiving() && b->receiving()) {
1093 return b_is_better;
1094 }
pthatcher1 2016/07/13 21:17:22 Doesn't this change the order so that connected vs
honghaiz3 2016/07/14 04:54:20 I did not think that should have a major impact al
1095
1096 return 0;
1097 }
1098
1099 int P2PTransportChannel::CompareConnectionStatesWithDampening(
1100 const Connection* selected_conn,
1101 const Connection* new_conn,
pthatcher1 2016/07/13 21:17:23 CompareConnectionX should know about "selected" an
honghaiz3 2016/07/14 04:54:20 Done
1102 bool* new_conn_dampened) const {
1103 int cmp = CompareConnectionWriteAndConnectedStates(selected_conn, new_conn);
1104 if (cmp != 0) {
1105 return cmp;
1106 }
1107
1108 if (selected_conn->receiving() && !new_conn->receiving()) {
1109 return a_is_better;
1110 }
1111
1112 if (!selected_conn->receiving() && new_conn->receiving()) {
1113 // If |selected_conn| is not receiving and |new_conn| is receiving, we wait
1114 // for a short while before switching to the new connection.
1115 if (new_conn->first_received_since_channel_weak() != 0 &&
1116 rtc::TimeMillis() - new_conn->first_received_since_channel_weak() >=
1117 *config_.receiving_dampening_interval) {
pthatcher1 2016/07/13 21:17:22 I think it would make more sense to have the Conne
honghaiz3 2016/07/14 04:54:20 Done, somewhat different though.
1118 return b_is_better;
1119 }
1120 *new_conn_dampened = true;
1121 }
1122
1123 return 0;
1124 }
1125
1055 // Compares two connections based only on the candidate and network information. 1126 // Compares two connections based only on the candidate and network information.
1056 // Returns positive if |a| is better than |b|. 1127 // Returns positive if |a| is better than |b|.
1057 int P2PTransportChannel::CompareConnectionCandidates( 1128 int P2PTransportChannel::CompareConnectionCandidates(
1058 const Connection* a, 1129 const Connection* a,
1059 const Connection* b) const { 1130 const Connection* b) const {
1060 // Prefer lower network cost. 1131 // Prefer lower network cost.
1061 uint32_t a_cost = a->ComputeNetworkCost(); 1132 uint32_t a_cost = a->ComputeNetworkCost();
1062 uint32_t b_cost = b->ComputeNetworkCost(); 1133 uint32_t b_cost = b->ComputeNetworkCost();
1063 // Smaller cost is better. 1134 // Smaller cost is better.
1064 if (a_cost < b_cost) { 1135 if (a_cost < b_cost) {
(...skipping 10 matching lines...) Expand all
1075 if (a->priority() < b->priority()) { 1146 if (a->priority() < b->priority()) {
1076 return b_is_better; 1147 return b_is_better;
1077 } 1148 }
1078 1149
1079 // If we're still tied at this point, prefer a younger generation. 1150 // If we're still tied at this point, prefer a younger generation.
1080 // (Younger generation means a larger generation number). 1151 // (Younger generation means a larger generation number).
1081 return (a->remote_candidate().generation() + a->port()->generation()) - 1152 return (a->remote_candidate().generation() + a->port()->generation()) -
1082 (b->remote_candidate().generation() + b->port()->generation()); 1153 (b->remote_candidate().generation() + b->port()->generation());
1083 } 1154 }
1084 1155
1085 int P2PTransportChannel::CompareConnections(const Connection* a, 1156 int P2PTransportChannel::CompareConnectionsWithoutStates(
1086 const Connection* b) const { 1157 const Connection* a,
1158 const Connection* b) const {
1087 RTC_CHECK(a != nullptr); 1159 RTC_CHECK(a != nullptr);
1088 RTC_CHECK(b != nullptr); 1160 RTC_CHECK(b != nullptr);
1089 1161
1090 // We prefer to switch to a writable and receiving connection over a
1091 // non-writable or non-receiving connection, even if the latter has
1092 // been nominated by the controlling side.
1093 int state_cmp = CompareConnectionStates(a, b);
1094 if (state_cmp != 0) {
1095 return state_cmp;
1096 }
1097
1098 if (ice_role_ == ICEROLE_CONTROLLED) { 1162 if (ice_role_ == ICEROLE_CONTROLLED) {
1099 // Compare the connections based on the nomination states and the last data 1163 // Compare the connections based on the nomination states and the last data
1100 // received time if this is on the controlled side. 1164 // received time if this is on the controlled side.
1101 if (a->nominated() && !b->nominated()) { 1165 if (a->nominated() && !b->nominated()) {
1102 return a_is_better; 1166 return a_is_better;
1103 } 1167 }
1104 if (!a->nominated() && b->nominated()) { 1168 if (!a->nominated() && b->nominated()) {
1105 return b_is_better; 1169 return b_is_better;
1106 } 1170 }
1107 1171
1108 if (a->last_data_received() > b->last_data_received()) { 1172 if (a->last_data_received() > b->last_data_received()) {
1109 return a_is_better; 1173 return a_is_better;
1110 } 1174 }
1111 if (a->last_data_received() < b->last_data_received()) { 1175 if (a->last_data_received() < b->last_data_received()) {
1112 return b_is_better; 1176 return b_is_better;
1113 } 1177 }
1114 } 1178 }
1115 1179
1116 // Compare the network cost and priority. 1180 // Compare the network cost and priority.
1117 return CompareConnectionCandidates(a, b); 1181 return CompareConnectionCandidates(a, b);
1118 } 1182 }
1119 1183
1184 int P2PTransportChannel::CompareConnections(const Connection* a,
1185 const Connection* b) const {
1186 // We prefer to switch to a writable and receiving connection over a
1187 // non-writable or non-receiving connection, even if the latter has
1188 // been nominated by the controlling side.
1189 int cmp = CompareConnectionStates(a, b);
1190 if (cmp != 0) {
1191 return cmp;
1192 }
1193 cmp = CompareConnectionsWithoutStates(a, b);
1194 if (cmp != 0) {
1195 return cmp;
1196 }
1197 // Otherwise, compare the latency estimate. Note that a negative return value
1198 // indicates |b| is better.
1199 return b->rtt() - a->rtt();
1200 }
1201
1120 bool P2PTransportChannel::PresumedWritable(const Connection* conn) const { 1202 bool P2PTransportChannel::PresumedWritable(const Connection* conn) const {
1121 return (conn->write_state() == Connection::STATE_WRITE_INIT && 1203 return (conn->write_state() == Connection::STATE_WRITE_INIT &&
1122 config_.presume_writable_when_fully_relayed && 1204 config_.presume_writable_when_fully_relayed &&
1123 conn->local_candidate().type() == RELAY_PORT_TYPE && 1205 conn->local_candidate().type() == RELAY_PORT_TYPE &&
1124 (conn->remote_candidate().type() == RELAY_PORT_TYPE || 1206 (conn->remote_candidate().type() == RELAY_PORT_TYPE ||
1125 conn->remote_candidate().type() == PRFLX_PORT_TYPE)); 1207 conn->remote_candidate().type() == PRFLX_PORT_TYPE));
1126 } 1208 }
1127 1209
1128 // Sort the available connections to find the best one. We also monitor 1210 // Sort the available connections to find the best one. We also monitor
1129 // the number of available connections and the current state. 1211 // the number of available connections and the current state.
1130 void P2PTransportChannel::SortConnectionsAndUpdateState() { 1212 void P2PTransportChannel::SortConnectionsAndUpdateState() {
1131 ASSERT(worker_thread_ == rtc::Thread::Current()); 1213 ASSERT(worker_thread_ == rtc::Thread::Current());
1132 1214
1133 // Make sure the connection states are up-to-date since this affects how they 1215 // Make sure the connection states are up-to-date since this affects how they
1134 // will be sorted. 1216 // will be sorted.
1135 UpdateConnectionStates(); 1217 UpdateConnectionStates();
1136 1218
1137 // Any changes after this point will require a re-sort. 1219 // Any changes after this point will require a re-sort.
1138 sort_dirty_ = false; 1220 sort_dirty_ = false;
1139 1221
1140 // Find the best alternative connection by sorting. It is important to note 1222 // Find the best alternative connection by sorting. It is important to note
1141 // that amongst equal preference, writable connections, this will choose the 1223 // that amongst equal preference, writable connections, this will choose the
1142 // one whose estimated latency is lowest. So it is the only one that we 1224 // one whose estimated latency is lowest. So it is the only one that we
1143 // need to consider switching to. 1225 // need to consider switching to.
1144 std::stable_sort(connections_.begin(), connections_.end(), 1226 std::stable_sort(connections_.begin(), connections_.end(),
1145 [this](const Connection* a, const Connection* b) { 1227 [this](const Connection* a, const Connection* b) {
1146 int cmp = CompareConnections(a, b); 1228 return CompareConnections(a, b) > 0;
pthatcher1 2016/07/13 21:17:22 I think it would be less risky to leave the Compar
honghaiz3 2016/07/14 04:54:20 Done.
1147 if (cmp != 0) {
1148 return cmp > 0;
1149 }
1150 1229
1151 // Otherwise, sort based on latency estimate.
1152 return a->rtt() < b->rtt();
1153 }); 1230 });
1154 1231
1155 LOG(LS_VERBOSE) << "Sorting " << connections_.size() 1232 LOG(LS_VERBOSE) << "Sorting " << connections_.size()
1156 << " available connections:"; 1233 << " available connections:";
1157 for (size_t i = 0; i < connections_.size(); ++i) { 1234 for (size_t i = 0; i < connections_.size(); ++i) {
1158 LOG(LS_VERBOSE) << connections_[i]->ToString(); 1235 LOG(LS_VERBOSE) << connections_[i]->ToString();
1159 } 1236 }
1160 1237
1161 Connection* top_connection = 1238 Connection* top_connection =
1162 (connections_.size() > 0) ? connections_[0] : nullptr; 1239 (connections_.size() > 0) ? connections_[0] : nullptr;
1163 1240
1164 // If necessary, switch to the new choice. Note that |top_connection| doesn't 1241 // If necessary, switch to the new choice. Note that |top_connection| doesn't
1165 // have to be writable to become the selected connection although it will 1242 // have to be writable to become the selected connection although it will
1166 // have higher priority if it is writable. 1243 // have higher priority if it is writable.
1167 if (ShouldSwitchSelectedConnection(top_connection)) { 1244 if (ShouldSwitchSelectedConnection(top_connection)) {
1168 LOG(LS_INFO) << "Switching selected connection after sorting: " 1245 LOG(LS_INFO) << "Switching selected connection after sorting";
1169 << top_connection->ToString();
1170 SwitchSelectedConnection(top_connection); 1246 SwitchSelectedConnection(top_connection);
1171 } 1247 }
1172 1248
1173 // The controlled side can prune only if the selected connection has been 1249 // The controlled side can prune only if the selected connection has been
1174 // nominated because otherwise it may prune the connection that will be 1250 // nominated because otherwise it may prune the connection that will be
1175 // selected by the controlling side. 1251 // selected by the controlling side.
1176 // TODO(honghaiz): This is not enough to prevent a connection from being 1252 // TODO(honghaiz): This is not enough to prevent a connection from being
1177 // pruned too early because with aggressive nomination, the controlling side 1253 // pruned too early because with aggressive nomination, the controlling side
1178 // will nominate every connection until it becomes writable. 1254 // will nominate every connection until it becomes writable.
1179 if (ice_role_ == ICEROLE_CONTROLLING || 1255 if (ice_role_ == ICEROLE_CONTROLLING ||
(...skipping 60 matching lines...) Expand 10 before | Expand all | Expand 10 after
1240 } 1316 }
1241 } 1317 }
1242 1318
1243 // Change the selected connection, and let listeners know. 1319 // Change the selected connection, and let listeners know.
1244 void P2PTransportChannel::SwitchSelectedConnection(Connection* conn) { 1320 void P2PTransportChannel::SwitchSelectedConnection(Connection* conn) {
1245 // Note: if conn is NULL, the previous |selected_connection_| has been 1321 // Note: if conn is NULL, the previous |selected_connection_| has been
1246 // destroyed, so don't use it. 1322 // destroyed, so don't use it.
1247 Connection* old_selected_connection = selected_connection_; 1323 Connection* old_selected_connection = selected_connection_;
1248 selected_connection_ = conn; 1324 selected_connection_ = conn;
1249 if (selected_connection_) { 1325 if (selected_connection_) {
1326 if (pending_selected_connection_ == selected_connection_) {
1327 pending_selected_connection_ = nullptr;
1328 }
1250 if (old_selected_connection) { 1329 if (old_selected_connection) {
1251 LOG_J(LS_INFO, this) << "Previous selected connection: " 1330 LOG_J(LS_INFO, this) << "Previous selected connection: "
1252 << old_selected_connection->ToString(); 1331 << old_selected_connection->ToString();
1253 } 1332 }
1254 LOG_J(LS_INFO, this) << "New selected connection: " 1333 LOG_J(LS_INFO, this) << "New selected connection: "
1255 << selected_connection_->ToString(); 1334 << selected_connection_->ToString();
1256 SignalRouteChange(this, selected_connection_->remote_candidate()); 1335 SignalRouteChange(this, selected_connection_->remote_candidate());
1257 // This is a temporary, but safe fix to webrtc issue 5705. 1336 // This is a temporary, but safe fix to webrtc issue 5705.
1258 // TODO(honghaiz): Make all EWOULDBLOCK error routed through the transport 1337 // TODO(honghaiz): Make all EWOULDBLOCK error routed through the transport
1259 // channel so that it knows whether the media channel is allowed to 1338 // channel so that it knows whether the media channel is allowed to
(...skipping 148 matching lines...) Expand 10 before | Expand all | Expand 10 after
1408 ASSERT(false); 1487 ASSERT(false);
1409 break; 1488 break;
1410 } 1489 }
1411 } 1490 }
1412 1491
1413 // Handle queued up check-and-ping request 1492 // Handle queued up check-and-ping request
1414 void P2PTransportChannel::OnCheckAndPing() { 1493 void P2PTransportChannel::OnCheckAndPing() {
1415 // Make sure the states of the connections are up-to-date (since this affects 1494 // Make sure the states of the connections are up-to-date (since this affects
1416 // which ones are pingable). 1495 // which ones are pingable).
1417 UpdateConnectionStates(); 1496 UpdateConnectionStates();
1497 if (pending_selected_connection_) {
1498 if (ShouldSwitchSelectedConnection(pending_selected_connection_)) {
1499 LOG(LS_INFO) << "Switching selected connection to a pending one";
1500 SwitchSelectedConnection(pending_selected_connection_);
1501 } else if (!weak()) {
1502 pending_selected_connection_ = nullptr;
1503 }
1504 }
pthatcher1 2016/07/13 21:17:23 This code, or the equivalent, really should be ins
honghaiz3 2016/07/14 04:54:20 This serves the purpose of periodical checking the
1505
1418 // When the selected connection is not receiving or not writable, or any 1506 // When the selected connection is not receiving or not writable, or any
1419 // active connection has not been pinged enough times, use the weak ping 1507 // active connection has not been pinged enough times, use the weak ping
1420 // interval. 1508 // interval.
1421 bool need_more_pings_at_weak_interval = std::any_of( 1509 bool need_more_pings_at_weak_interval = std::any_of(
1422 connections_.begin(), connections_.end(), [](Connection* conn) { 1510 connections_.begin(), connections_.end(), [](Connection* conn) {
1423 return conn->active() && 1511 return conn->active() &&
1424 conn->num_pings_sent() < MIN_PINGS_AT_WEAK_PING_INTERVAL; 1512 conn->num_pings_sent() < MIN_PINGS_AT_WEAK_PING_INTERVAL;
1425 }); 1513 });
1426 int ping_interval = (weak() || need_more_pings_at_weak_interval) 1514 int ping_interval = (weak() || need_more_pings_at_weak_interval)
1427 ? weak_ping_interval_ 1515 ? weak_ping_interval_
(...skipping 187 matching lines...) Expand 10 before | Expand all | Expand 10 after
1615 LOG_J(LS_INFO, this) << "Removed connection (" 1703 LOG_J(LS_INFO, this) << "Removed connection ("
1616 << static_cast<int>(connections_.size()) << " remaining)"; 1704 << static_cast<int>(connections_.size()) << " remaining)";
1617 1705
1618 // If this is currently the selected connection, then we need to pick a new 1706 // If this is currently the selected connection, then we need to pick a new
1619 // one. The call to SortConnectionsAndUpdateState will pick a new one. It 1707 // one. The call to SortConnectionsAndUpdateState will pick a new one. It
1620 // looks at the current selected connection in order to avoid switching 1708 // looks at the current selected connection in order to avoid switching
1621 // between fairly similar ones. Since this connection is no longer an option, 1709 // between fairly similar ones. Since this connection is no longer an option,
1622 // we can just set selected to nullptr and re-choose a best assuming that 1710 // we can just set selected to nullptr and re-choose a best assuming that
1623 // there was no selected connection. 1711 // there was no selected connection.
1624 if (selected_connection_ == connection) { 1712 if (selected_connection_ == connection) {
1625 LOG(LS_INFO) << "selected connection destroyed. Will choose a new one."; 1713 LOG(LS_INFO) << "Selected connection destroyed. Will choose a new one.";
1626 SwitchSelectedConnection(nullptr); 1714 SwitchSelectedConnection(nullptr);
1627 RequestSortAndStateUpdate(); 1715 RequestSortAndStateUpdate();
1628 } else { 1716 } else {
1629 // If a non-selected connection was destroyed, we don't need to re-sort but 1717 // If a non-selected connection was destroyed, we don't need to re-sort but
1630 // we do need to update state, because we could be switching to "failed" or 1718 // we do need to update state, because we could be switching to "failed" or
1631 // "completed". 1719 // "completed".
1632 UpdateState(); 1720 UpdateState();
1633 } 1721 }
1634 } 1722 }
1635 1723
(...skipping 86 matching lines...) Expand 10 before | Expand all | Expand 10 after
1722 return; 1810 return;
1723 1811
1724 // Let the client know of an incoming packet 1812 // Let the client know of an incoming packet
1725 SignalReadPacket(this, data, len, packet_time, 0); 1813 SignalReadPacket(this, data, len, packet_time, 0);
1726 1814
1727 // May need to switch the sending connection based on the receiving media path 1815 // May need to switch the sending connection based on the receiving media path
1728 // if this is the controlled side. 1816 // if this is the controlled side.
1729 if (ice_role_ == ICEROLE_CONTROLLED && 1817 if (ice_role_ == ICEROLE_CONTROLLED &&
1730 ShouldSwitchSelectedConnection(connection)) { 1818 ShouldSwitchSelectedConnection(connection)) {
1731 LOG(LS_INFO) << "Switching selected connection on controlled side due to " 1819 LOG(LS_INFO) << "Switching selected connection on controlled side due to "
1732 << "data received: " << connection->ToString(); 1820 << "data received";
1733 SwitchSelectedConnection(connection); 1821 SwitchSelectedConnection(connection);
1734 } 1822 }
1735 } 1823 }
1736 1824
1737 void P2PTransportChannel::OnSentPacket(const rtc::SentPacket& sent_packet) { 1825 void P2PTransportChannel::OnSentPacket(const rtc::SentPacket& sent_packet) {
1738 ASSERT(worker_thread_ == rtc::Thread::Current()); 1826 ASSERT(worker_thread_ == rtc::Thread::Current());
1739 1827
1740 SignalSentPacket(this, sent_packet); 1828 SignalSentPacket(this, sent_packet);
1741 } 1829 }
1742 1830
(...skipping 114 matching lines...) Expand 10 before | Expand all | Expand 10 after
1857 1945
1858 // During the initial state when nothing has been pinged yet, return the first 1946 // During the initial state when nothing has been pinged yet, return the first
1859 // one in the ordered |connections_|. 1947 // one in the ordered |connections_|.
1860 return *(std::find_if(connections_.begin(), connections_.end(), 1948 return *(std::find_if(connections_.begin(), connections_.end(),
1861 [conn1, conn2](Connection* conn) { 1949 [conn1, conn2](Connection* conn) {
1862 return conn == conn1 || conn == conn2; 1950 return conn == conn1 || conn == conn2;
1863 })); 1951 }));
1864 } 1952 }
1865 1953
1866 } // namespace cricket 1954 } // 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