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

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

Issue 2069493002: Do not switch best connection on the controlled side too frequently (Closed) Base URL: https://chromium.googlesource.com/external/webrtc@master
Patch Set: Updates a comment Created 4 years, 6 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
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 35 matching lines...) Expand 10 before | Expand all | Expand 10 after
46 if (!origin_port) 46 if (!origin_port)
47 return cricket::PortInterface::ORIGIN_MESSAGE; 47 return cricket::PortInterface::ORIGIN_MESSAGE;
48 else if (port == origin_port) 48 else if (port == origin_port)
49 return cricket::PortInterface::ORIGIN_THIS_PORT; 49 return cricket::PortInterface::ORIGIN_THIS_PORT;
50 else 50 else
51 return cricket::PortInterface::ORIGIN_OTHER_PORT; 51 return cricket::PortInterface::ORIGIN_OTHER_PORT;
52 } 52 }
53 53
54 // Compares two connections based only on the candidate and network information. 54 // Compares two connections based only on the candidate and network information.
55 // Returns positive if |a| is better than |b|. 55 // Returns positive if |a| is better than |b|.
56 int CompareConnectionCandidates(cricket::Connection* a, 56 int CompareConnectionCandidates(const cricket::Connection* a,
57 cricket::Connection* b) { 57 const cricket::Connection* b) {
58 uint32_t a_cost = a->ComputeNetworkCost(); 58 uint32_t a_cost = a->ComputeNetworkCost();
59 uint32_t b_cost = b->ComputeNetworkCost(); 59 uint32_t b_cost = b->ComputeNetworkCost();
60 // Smaller cost is better. 60 // Smaller cost is better.
61 if (a_cost < b_cost) { 61 if (a_cost < b_cost) {
62 return 1; 62 return 1;
63 } 63 }
64 if (a_cost > b_cost) { 64 if (a_cost > b_cost) {
65 return -1; 65 return -1;
66 } 66 }
67 67
68 // Compare connection priority. Lower values get sorted last. 68 // Compare connection priority. Lower values get sorted last.
69 if (a->priority() > b->priority()) 69 if (a->priority() > b->priority())
70 return 1; 70 return 1;
71 if (a->priority() < b->priority()) 71 if (a->priority() < b->priority())
72 return -1; 72 return -1;
73 73
74 // If we're still tied at this point, prefer a younger generation. 74 // If we're still tied at this point, prefer a younger generation.
75 return (a->remote_candidate().generation() + a->port()->generation()) - 75 return (a->remote_candidate().generation() + a->port()->generation()) -
76 (b->remote_candidate().generation() + b->port()->generation()); 76 (b->remote_candidate().generation() + b->port()->generation());
77 } 77 }
78 78
79 // Compare two connections based on their writing, receiving, and connected 79 // Compare two connections based on their writing, receiving, and connected
80 // states. 80 // states.
81 int CompareConnectionStates(cricket::Connection* a, cricket::Connection* b) { 81 int CompareConnectionStates(const cricket::Connection* a,
82 const cricket::Connection* b) {
82 // Sort based on write-state. Better states have lower values. 83 // Sort based on write-state. Better states have lower values.
83 if (a->write_state() < b->write_state()) 84 if (a->write_state() < b->write_state())
84 return 1; 85 return 1;
85 if (a->write_state() > b->write_state()) 86 if (a->write_state() > b->write_state())
86 return -1; 87 return -1;
87 88
88 // We prefer a receiving connection to a non-receiving, higher-priority 89 // We prefer a receiving connection to a non-receiving, higher-priority
89 // connection when sorting connections and choosing which connection to 90 // connection when sorting connections and choosing which connection to
90 // switch to. 91 // switch to.
91 if (a->receiving() && !b->receiving()) 92 if (a->receiving() && !b->receiving())
92 return 1; 93 return 1;
93 if (!a->receiving() && b->receiving()) 94 if (!a->receiving() && b->receiving())
94 return -1; 95 return -1;
95 96
96 // WARNING: Some complexity here about TCP reconnecting. 97 // WARNING: Some complexity here about TCP reconnecting.
97 // When a TCP connection fails because of a TCP socket disconnecting, the 98 // When a TCP connection fails because of a TCP socket disconnecting, the
98 // active side of the connection will attempt to reconnect for 5 seconds while 99 // active side of the connection will attempt to reconnect for 5 seconds while
99 // pretending to be writable (the connection is not set to the unwritable 100 // pretending to be writable (the connection is not set to the unwritable
100 // state). On the passive side, the connection also remains writable even 101 // state). On the passive side, the connection also remains writable even
101 // though it is disconnected, and a new connection is created when the active 102 // though it is disconnected, and a new connection is created when the active
102 // side connects. At that point, there are two TCP connections on the passive 103 // side connects. At that point, there are two TCP connections on the passive
103 // side: 1. the old, disconnected one that is pretending to be writable, and 104 // side: 1. the old, disconnected one that is pretending to be writable, and
104 // 2. the new, connected one that is maybe not yet writable. For purposes of 105 // 2. the new, connected one that is maybe not yet writable. For purposes of
105 // pruning, pinging, and selecting the best connection, we want to treat the 106 // pruning, pinging, and selecting the connection to use, we want to treat the
106 // new connection as "better" than the old one. We could add a method called 107 // new connection as "better" than the old one. We could add a method called
107 // something like Connection::ImReallyBadEvenThoughImWritable, but that is 108 // something like Connection::ImReallyBadEvenThoughImWritable, but that is
108 // equivalent to the existing Connection::connected(), which we already have. 109 // equivalent to the existing Connection::connected(), which we already have.
109 // So, in code throughout this file, we'll check whether the connection is 110 // So, in code throughout this file, we'll check whether the connection is
110 // connected() or not, and if it is not, treat it as "worse" than a connected 111 // connected() or not, and if it is not, treat it as "worse" than a connected
111 // one, even though it's writable. In the code below, we're doing so to make 112 // one, even though it's writable. In the code below, we're doing so to make
112 // sure we treat a new writable connection as better than an old disconnected 113 // sure we treat a new writable connection as better than an old disconnected
113 // connection. 114 // connection.
114 115
115 // In the case where we reconnect TCP connections, the original best 116 // In the case where we reconnect TCP connections, the original best
116 // connection is disconnected without changing to WRITE_TIMEOUT. In this case, 117 // connection is disconnected without changing to WRITE_TIMEOUT. In this case,
117 // the new connection, when it becomes writable, should have higher priority. 118 // the new connection, when it becomes writable, should have higher priority.
118 if (a->write_state() == cricket::Connection::STATE_WRITABLE && 119 if (a->write_state() == cricket::Connection::STATE_WRITABLE &&
119 b->write_state() == cricket::Connection::STATE_WRITABLE) { 120 b->write_state() == cricket::Connection::STATE_WRITABLE) {
120 if (a->connected() && !b->connected()) { 121 if (a->connected() && !b->connected()) {
121 return 1; 122 return 1;
122 } 123 }
123 if (!a->connected() && b->connected()) { 124 if (!a->connected() && b->connected()) {
124 return -1; 125 return -1;
125 } 126 }
126 } 127 }
127 return 0; 128 return 0;
128 } 129 }
129 130
130 int CompareConnections(cricket::Connection* a, cricket::Connection* b) {
131 int state_cmp = CompareConnectionStates(a, b);
132 if (state_cmp != 0) {
133 return state_cmp;
134 }
135 // Compare the candidate information.
136 return CompareConnectionCandidates(a, b);
137 }
138
139 // Wraps the comparison connection into a less than operator that puts higher
140 // priority writable connections first.
141 class ConnectionCompare {
142 public:
143 bool operator()(const cricket::Connection *ca,
144 const cricket::Connection *cb) {
145 cricket::Connection* a = const_cast<cricket::Connection*>(ca);
146 cricket::Connection* b = const_cast<cricket::Connection*>(cb);
147
148 // Compare first on writability and static preferences.
149 int cmp = CompareConnections(a, b);
150 if (cmp > 0)
151 return true;
152 if (cmp < 0)
153 return false;
154
155 // Otherwise, sort based on latency estimate.
156 return a->rtt() < b->rtt();
157
158 // Should we bother checking for the last connection that last received
159 // data? It would help rendezvous on the connection that is also receiving
160 // packets.
161 //
162 // TODO: Yes we should definitely do this. The TCP protocol gains
163 // efficiency by being used bidirectionally, as opposed to two separate
164 // unidirectional streams. This test should probably occur before
165 // comparison of local prefs (assuming combined prefs are the same). We
166 // need to be careful though, not to bounce back and forth with both sides
167 // trying to rendevous with the other.
168 }
169 };
170
171 // Determines whether we should switch between two connections, based first on
172 // connection states, static preferences, and then (if those are equal) on
173 // latency estimates.
174 bool ShouldSwitch(cricket::Connection* a_conn,
175 cricket::Connection* b_conn,
176 cricket::IceRole ice_role) {
177 if (a_conn == b_conn)
178 return false;
179
180 if (!a_conn || !b_conn) // don't think the latter should happen
181 return true;
182
183 // We prefer to switch to a writable and receiving connection over a
184 // non-writable or non-receiving connection, even if the latter has
185 // been nominated by the controlling side.
186 int state_cmp = CompareConnectionStates(a_conn, b_conn);
187 if (state_cmp != 0) {
188 return state_cmp < 0;
189 }
190 if (ice_role == cricket::ICEROLE_CONTROLLED && a_conn->nominated()) {
191 LOG(LS_VERBOSE) << "Controlled side did not switch due to nominated status";
192 return false;
193 }
194
195 int prefs_cmp = CompareConnectionCandidates(a_conn, b_conn);
196 if (prefs_cmp != 0) {
197 return prefs_cmp < 0;
198 }
199
200 return b_conn->rtt() <= a_conn->rtt() + kMinImprovement;
201 }
202
203 } // unnamed namespace 131 } // unnamed namespace
204 132
205 namespace cricket { 133 namespace cricket {
206 134
207 // When the socket is unwritable, we will use 10 Kbps (ignoring IP+UDP headers) 135 // When the socket is unwritable, we will use 10 Kbps (ignoring IP+UDP headers)
208 // for pinging. When the socket is writable, we will use only 1 Kbps because 136 // for pinging. When the socket is writable, we will use only 1 Kbps because
209 // we don't want to degrade the quality on a modem. These numbers should work 137 // we don't want to degrade the quality on a modem. These numbers should work
210 // well on a 28.8K modem, which is the slowest connection on which the voice 138 // well on a 28.8K modem, which is the slowest connection on which the voice
211 // quality is reasonable at all. 139 // quality is reasonable at all.
212 static const int PING_PACKET_SIZE = 60 * 8; 140 static const int PING_PACKET_SIZE = 60 * 8;
213 // STRONG_PING_INTERVAL (480ms) is applied when the best connection is both 141 // STRONG_PING_INTERVAL (480ms) is applied when the selected connection is both
214 // writable and receiving. 142 // writable and receiving.
215 static const int STRONG_PING_INTERVAL = 1000 * PING_PACKET_SIZE / 1000; 143 static const int STRONG_PING_INTERVAL = 1000 * PING_PACKET_SIZE / 1000;
216 // WEAK_PING_INTERVAL (48ms) is applied when the best connection is either not 144 // WEAK_PING_INTERVAL (48ms) is applied when the selected connection is either
217 // writable or not receiving. 145 // not writable or not receiving.
218 const int WEAK_PING_INTERVAL = 1000 * PING_PACKET_SIZE / 10000; 146 const int WEAK_PING_INTERVAL = 1000 * PING_PACKET_SIZE / 10000;
219 147
220 // If the current best connection is both writable and receiving, then we will 148 // If the current selected connection is both writable and receiving, then we
221 // also try hard to make sure it is pinged at this rate (a little less than 149 // will also try hard to make sure it is pinged at this rate (a little less
222 // 2 * STRONG_PING_INTERVAL). 150 // than 2 * STRONG_PING_INTERVAL).
223 static const int MAX_CURRENT_STRONG_INTERVAL = 900; // ms 151 static const int MAX_CURRENT_STRONG_INTERVAL = 900; // ms
224 152
225 static const int MIN_CHECK_RECEIVING_INTERVAL = 50; // ms 153 static const int MIN_CHECK_RECEIVING_INTERVAL = 50; // ms
226 154
227 P2PTransportChannel::P2PTransportChannel(const std::string& transport_name, 155 P2PTransportChannel::P2PTransportChannel(const std::string& transport_name,
228 int component, 156 int component,
229 P2PTransport* transport, 157 P2PTransport* transport,
230 PortAllocator* allocator) 158 PortAllocator* allocator)
231 : P2PTransportChannel(transport_name, component, allocator) {} 159 : P2PTransportChannel(transport_name, component, allocator) {}
232 160
233 P2PTransportChannel::P2PTransportChannel(const std::string& transport_name, 161 P2PTransportChannel::P2PTransportChannel(const std::string& transport_name,
234 int component, 162 int component,
235 PortAllocator* allocator) 163 PortAllocator* allocator)
236 : TransportChannelImpl(transport_name, component), 164 : TransportChannelImpl(transport_name, component),
237 allocator_(allocator), 165 allocator_(allocator),
238 worker_thread_(rtc::Thread::Current()), 166 worker_thread_(rtc::Thread::Current()),
239 incoming_only_(false), 167 incoming_only_(false),
240 error_(0), 168 error_(0),
241 best_connection_(NULL),
242 pending_best_connection_(NULL),
243 sort_dirty_(false), 169 sort_dirty_(false),
244 remote_ice_mode_(ICEMODE_FULL), 170 remote_ice_mode_(ICEMODE_FULL),
245 ice_role_(ICEROLE_UNKNOWN), 171 ice_role_(ICEROLE_UNKNOWN),
246 tiebreaker_(0), 172 tiebreaker_(0),
247 gathering_state_(kIceGatheringNew), 173 gathering_state_(kIceGatheringNew),
248 check_receiving_interval_(MIN_CHECK_RECEIVING_INTERVAL * 5), 174 check_receiving_interval_(MIN_CHECK_RECEIVING_INTERVAL * 5),
249 config_(MIN_CHECK_RECEIVING_INTERVAL * 50 /* receiving_timeout */, 175 config_(MIN_CHECK_RECEIVING_INTERVAL * 50 /* receiving_timeout */,
250 0 /* backup_connection_ping_interval */, 176 0 /* backup_connection_ping_interval */,
251 false /* gather_continually */, 177 false /* gather_continually */,
252 false /* prioritize_most_likely_candidate_pairs */, 178 false /* prioritize_most_likely_candidate_pairs */,
(...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after
294 connection->SignalReadyToSend.connect( 220 connection->SignalReadyToSend.connect(
295 this, &P2PTransportChannel::OnReadyToSend); 221 this, &P2PTransportChannel::OnReadyToSend);
296 connection->SignalStateChange.connect( 222 connection->SignalStateChange.connect(
297 this, &P2PTransportChannel::OnConnectionStateChange); 223 this, &P2PTransportChannel::OnConnectionStateChange);
298 connection->SignalDestroyed.connect( 224 connection->SignalDestroyed.connect(
299 this, &P2PTransportChannel::OnConnectionDestroyed); 225 this, &P2PTransportChannel::OnConnectionDestroyed);
300 connection->SignalNominated.connect(this, &P2PTransportChannel::OnNominated); 226 connection->SignalNominated.connect(this, &P2PTransportChannel::OnNominated);
301 had_connection_ = true; 227 had_connection_ = true;
302 } 228 }
303 229
230 int P2PTransportChannel::CompareConnections(
pthatcher1 2016/06/21 07:16:53 Can you call this CompareConnectionIncludingStates
honghaiz3 2016/06/22 08:03:16 Done.
231 const cricket::Connection* a,
232 const cricket::Connection* b) const {
233 RTC_CHECK(a != nullptr);
234 RTC_CHECK(b != nullptr);
235
236 // We prefer to switch to a writable and receiving connection over a
237 // non-writable or non-receiving connection, even if the latter has
238 // been nominated by the controlling side.
239 int state_cmp = CompareConnectionStates(a, b);
240 if (state_cmp != 0) {
241 return state_cmp;
242 }
243 return CompareConnectionsBase(a, b);
244 }
245
246 int P2PTransportChannel::CompareConnectionsBase(
pthatcher1 2016/06/21 07:16:53 Can you call this CompareConnectionsExcludingState
honghaiz3 2016/06/22 08:03:16 Done.
247 const cricket::Connection* a,
248 const cricket::Connection* b) const {
249 if (ice_role_ == cricket::ICEROLE_CONTROLLED) {
250 // Compare the connections based on the nomination states and the last data
251 // received time if this is on the controlled side.
252 if (a->nominated() != b->nominated()) {
253 return b->nominated() ? -1 : 1;
254 }
255
256 if (a->last_data_received() > b->last_data_received()) {
Taylor Brandstetter 2016/06/21 18:33:25 What happens if the controlled side stops sending
pthatcher1 2016/06/22 06:36:34 We could still switch to a higher priority candida
honghaiz3 2016/06/22 08:03:16 If the controlling side stops sending data, the co
honghaiz3 2016/06/22 08:03:16 Acknowledged.
257 return 1;
258 }
259 if (a->last_data_received() < b->last_data_received()) {
260 return -1;
261 }
262 }
263
264 // Compare the network cost and priority.
265 return CompareConnectionCandidates(a, b);
266 }
267
268 // Determines whether we should switch the selected connection to
269 // |new_connection| based the writable/receiving state, the nomination state,
270 // and the last data received time. This prevents the controlled side from
271 // switching the selected connection too frequently when the controlling side
272 // is doing aggressive nominations. The precedence of the connection switching
273 // criteria is as follows:
274 // i) write/receiving/connected states
275 // ii) For controlled side,
276 // a) nomination state,
277 // b) last data received time.
278 // iii) Lower cost / higher priority.
279 // iv) rtt.
280 // TODO(honghaiz): Stop the aggressive nomination on the controlling side and
281 // implement the ice-renomination option.
282 bool P2PTransportChannel::ShouldSwitchConnection(
pthatcher1 2016/06/21 07:16:53 Can you call this ShouldSwitchSelectedConnection?
honghaiz3 2016/06/22 08:03:16 Done.
283 cricket::Connection* new_connection) const {
284 RTC_CHECK(new_connection != nullptr);
285 RTC_DCHECK(selected_connection_ != new_connection);
pthatcher1 2016/06/21 07:16:52 I think it would simply be better to do this: if
honghaiz3 2016/06/22 08:03:16 Done.
286
287 if (selected_connection_ == nullptr) {
288 return true;
289 }
290 int cmp = CompareConnections(selected_connection_, new_connection);
291 if (cmp != 0) {
292 return cmp < 0;
293 }
294
295 // Lastly, switch only if rtt has improved by a margin.
Taylor Brandstetter 2016/06/21 18:33:25 Odd to say "lastly" if there's no "firstly". Maybe
pthatcher1 2016/06/22 06:36:34 I think that's what the big comment before the met
honghaiz3 2016/06/22 08:03:16 Acknowledged.
honghaiz3 2016/06/22 08:03:16 Revised the comments.
296 return new_connection->rtt() <= selected_connection_->rtt() + kMinImprovement;
297 }
298
304 void P2PTransportChannel::SetIceRole(IceRole ice_role) { 299 void P2PTransportChannel::SetIceRole(IceRole ice_role) {
305 ASSERT(worker_thread_ == rtc::Thread::Current()); 300 ASSERT(worker_thread_ == rtc::Thread::Current());
306 if (ice_role_ != ice_role) { 301 if (ice_role_ != ice_role) {
307 ice_role_ = ice_role; 302 ice_role_ = ice_role;
308 for (std::vector<PortInterface *>::iterator it = ports_.begin(); 303 for (std::vector<PortInterface *>::iterator it = ports_.begin();
309 it != ports_.end(); ++it) { 304 it != ports_.end(); ++it) {
310 (*it)->SetIceRole(ice_role); 305 (*it)->SetIceRole(ice_role);
311 } 306 }
312 } 307 }
313 } 308 }
(...skipping 408 matching lines...) Expand 10 before | Expand all | Expand 10 after
722 return nullptr; 717 return nullptr;
723 } 718 }
724 *generation = params.rend() - it - 1; 719 *generation = params.rend() - it - 1;
725 return &(*it); 720 return &(*it);
726 } 721 }
727 722
728 void P2PTransportChannel::OnNominated(Connection* conn) { 723 void P2PTransportChannel::OnNominated(Connection* conn) {
729 ASSERT(worker_thread_ == rtc::Thread::Current()); 724 ASSERT(worker_thread_ == rtc::Thread::Current());
730 ASSERT(ice_role_ == ICEROLE_CONTROLLED); 725 ASSERT(ice_role_ == ICEROLE_CONTROLLED);
731 726
732 if (conn->write_state() == Connection::STATE_WRITABLE) { 727 if (selected_connection_ == conn) {
733 if (best_connection_ != conn) { 728 return;
734 pending_best_connection_ = NULL;
735 LOG(LS_INFO) << "Switching best connection on controlled side: "
736 << conn->ToString();
737 SwitchBestConnectionTo(conn);
738 // Now we have selected the best connection, time to prune other existing
739 // connections and update the read/write state of the channel.
740 RequestSort();
741 }
742 } else {
743 LOG(LS_INFO) << "Not switching the best connection on controlled side yet,"
744 << " because it's not writable: " << conn->ToString();
745 pending_best_connection_ = conn;
746 } 729 }
730
731 if (!ShouldSwitchConnection(conn)) {
732 LOG(LS_INFO)
733 << "Not switching the selected connection on controlled side yet: "
734 << conn->ToString();
735 return;
736 }
737
738 LOG(LS_INFO)
739 << "Switching selected connection on controlled side due to nomination: "
740 << conn->ToString();
741 SwitchSelectedConnection(conn);
742 // Now we have selected the selected connection, time to prune other existing
Taylor Brandstetter 2016/06/21 18:33:25 "Now that we have selected a connection, it's time
honghaiz3 2016/06/22 08:03:16 Done.
743 // connections and update the read/write state of the channel.
744 RequestSort();
747 } 745 }
748 746
749 void P2PTransportChannel::AddRemoteCandidate(const Candidate& candidate) { 747 void P2PTransportChannel::AddRemoteCandidate(const Candidate& candidate) {
750 ASSERT(worker_thread_ == rtc::Thread::Current()); 748 ASSERT(worker_thread_ == rtc::Thread::Current());
751 749
752 uint32_t generation = GetRemoteCandidateGeneration(candidate); 750 uint32_t generation = GetRemoteCandidateGeneration(candidate);
753 // If a remote candidate with a previous generation arrives, drop it. 751 // If a remote candidate with a previous generation arrives, drop it.
754 if (generation < remote_ice_generation()) { 752 if (generation < remote_ice_generation()) {
755 LOG(LS_WARNING) << "Dropping a remote candidate because its ufrag " 753 LOG(LS_WARNING) << "Dropping a remote candidate because its ufrag "
756 << candidate.username() 754 << candidate.username()
(...skipping 226 matching lines...) Expand 10 before | Expand all | Expand 10 after
983 ASSERT(worker_thread_ == rtc::Thread::Current()); 981 ASSERT(worker_thread_ == rtc::Thread::Current());
984 982
985 const auto& found = options_.find(opt); 983 const auto& found = options_.find(opt);
986 if (found == options_.end()) { 984 if (found == options_.end()) {
987 return false; 985 return false;
988 } 986 }
989 *value = found->second; 987 *value = found->second;
990 return true; 988 return true;
991 } 989 }
992 990
993 // Send data to the other side, using our best connection. 991 // Send data to the other side, using our selected connection.
994 int P2PTransportChannel::SendPacket(const char *data, size_t len, 992 int P2PTransportChannel::SendPacket(const char *data, size_t len,
995 const rtc::PacketOptions& options, 993 const rtc::PacketOptions& options,
996 int flags) { 994 int flags) {
997 ASSERT(worker_thread_ == rtc::Thread::Current()); 995 ASSERT(worker_thread_ == rtc::Thread::Current());
998 if (flags != 0) { 996 if (flags != 0) {
999 error_ = EINVAL; 997 error_ = EINVAL;
1000 return -1; 998 return -1;
1001 } 999 }
1002 if (best_connection_ == NULL) { 1000 if (selected_connection_ == NULL) {
1003 error_ = EWOULDBLOCK; 1001 error_ = EWOULDBLOCK;
1004 return -1; 1002 return -1;
1005 } 1003 }
1006 1004
1007 last_sent_packet_id_ = options.packet_id; 1005 last_sent_packet_id_ = options.packet_id;
1008 int sent = best_connection_->Send(data, len, options); 1006 int sent = selected_connection_->Send(data, len, options);
1009 if (sent <= 0) { 1007 if (sent <= 0) {
1010 ASSERT(sent < 0); 1008 ASSERT(sent < 0);
1011 error_ = best_connection_->GetError(); 1009 error_ = selected_connection_->GetError();
1012 } 1010 }
1013 return sent; 1011 return sent;
1014 } 1012 }
1015 1013
1016 bool P2PTransportChannel::GetStats(ConnectionInfos *infos) { 1014 bool P2PTransportChannel::GetStats(ConnectionInfos *infos) {
1017 ASSERT(worker_thread_ == rtc::Thread::Current()); 1015 ASSERT(worker_thread_ == rtc::Thread::Current());
1018 // Gather connection infos. 1016 // Gather connection infos.
1019 infos->clear(); 1017 infos->clear();
1020 1018
1021 for (Connection* connection : connections_) { 1019 for (Connection* connection : connections_) {
1022 ConnectionInfo info = connection->stats(); 1020 ConnectionInfo info = connection->stats();
1023 info.best_connection = (best_connection_ == connection); 1021 info.best_connection = (selected_connection_ == connection);
1024 info.receiving = connection->receiving(); 1022 info.receiving = connection->receiving();
1025 info.writable = (connection->write_state() == Connection::STATE_WRITABLE); 1023 info.writable = (connection->write_state() == Connection::STATE_WRITABLE);
1026 info.timeout = 1024 info.timeout =
1027 (connection->write_state() == Connection::STATE_WRITE_TIMEOUT); 1025 (connection->write_state() == Connection::STATE_WRITE_TIMEOUT);
1028 info.new_connection = !connection->reported(); 1026 info.new_connection = !connection->reported();
1029 connection->set_reported(true); 1027 connection->set_reported(true);
1030 info.rtt = connection->rtt(); 1028 info.rtt = connection->rtt();
1031 info.local_candidate = connection->local_candidate(); 1029 info.local_candidate = connection->local_candidate();
1032 info.remote_candidate = connection->remote_candidate(); 1030 info.remote_candidate = connection->remote_candidate();
1033 info.key = connection; 1031 info.key = connection;
(...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after
1072 // will be sorted. 1070 // will be sorted.
1073 UpdateConnectionStates(); 1071 UpdateConnectionStates();
1074 1072
1075 // Any changes after this point will require a re-sort. 1073 // Any changes after this point will require a re-sort.
1076 sort_dirty_ = false; 1074 sort_dirty_ = false;
1077 1075
1078 // Find the best alternative connection by sorting. It is important to note 1076 // Find the best alternative connection by sorting. It is important to note
1079 // that amongst equal preference, writable connections, this will choose the 1077 // that amongst equal preference, writable connections, this will choose the
1080 // one whose estimated latency is lowest. So it is the only one that we 1078 // one whose estimated latency is lowest. So it is the only one that we
1081 // need to consider switching to. 1079 // need to consider switching to.
1082 ConnectionCompare cmp; 1080 std::stable_sort(
1083 std::stable_sort(connections_.begin(), connections_.end(), cmp); 1081 connections_.begin(), connections_.end(),
1082 [this](const cricket::Connection* a, const cricket::Connection* b) {
1083 int cmp = CompareConnections(a, b);
1084 if (cmp != 0) {
1085 return cmp > 0;
1086 }
1087
1088 // Otherwise, sort based on latency estimate.
1089 return a->rtt() < b->rtt();
1090 });
1084 LOG(LS_VERBOSE) << "Sorting " << connections_.size() 1091 LOG(LS_VERBOSE) << "Sorting " << connections_.size()
1085 << " available connections:"; 1092 << " available connections:";
1086 for (size_t i = 0; i < connections_.size(); ++i) { 1093 for (size_t i = 0; i < connections_.size(); ++i) {
1087 LOG(LS_VERBOSE) << connections_[i]->ToString(); 1094 LOG(LS_VERBOSE) << connections_[i]->ToString();
1088 } 1095 }
1089 1096
1090 Connection* top_connection = 1097 Connection* top_connection =
1091 (connections_.size() > 0) ? connections_[0] : nullptr; 1098 (connections_.size() > 0) ? connections_[0] : nullptr;
1092 1099
1093 // If necessary, switch to the new choice. 1100 // If necessary, switch to the new choice. Note that |top_connection| doesn't
1094 // Note that |top_connection| doesn't have to be writable to become the best 1101 // have to be writable to become the selected connection although it will
1095 // connection although it will have higher priority if it is writable. 1102 // have higher priority if it is writable.
1096 if (ShouldSwitch(best_connection_, top_connection, ice_role_)) { 1103 if (top_connection != selected_connection_ &&
1097 LOG(LS_INFO) << "Switching best connection: " << top_connection->ToString(); 1104 ShouldSwitchConnection(top_connection)) {
pthatcher1 2016/06/21 07:16:53 Can you move this line into ShouldSwitchSelectedCo
honghaiz3 2016/06/22 08:03:16 Done.
1098 SwitchBestConnectionTo(top_connection); 1105 LOG(LS_INFO) << "Switching selected connection after sorting: "
1106 << top_connection->ToString();
1107 SwitchSelectedConnection(top_connection);
1099 } 1108 }
1100 1109
1101 // Controlled side can prune only if the best connection has been nominated. 1110 // Controlled side can prune only if the selected connection has been
pthatcher1 2016/06/21 07:16:53 Controlled side => The controlled side
honghaiz3 2016/06/22 08:03:16 Done.
1102 // because otherwise it may delete the connection that will be selected by 1111 // nominated because otherwise it may prune the connection that will be
1103 // the controlling side. 1112 // selected by the controlling side.
1104 if (ice_role_ == ICEROLE_CONTROLLING || best_nominated_connection()) { 1113 // TODO(honghaiz): This is not enough to prevent a connection from being
1114 // pruned too early because with aggressive nomination, the controlling side
1115 // will nominate every connection until it becomes writable. What we do now
1116 // is to un-prune a connection if a ping request comes with a nomination, or
1117 // new data is received on a nominated connection.
1118 if (ice_role_ == ICEROLE_CONTROLLING || selected_nominated_connection()) {
1105 PruneConnections(); 1119 PruneConnections();
1106 } 1120 }
1107 1121
1108 // Check if all connections are timedout. 1122 // Check if all connections are timedout.
1109 bool all_connections_timedout = true; 1123 bool all_connections_timedout = true;
1110 for (size_t i = 0; i < connections_.size(); ++i) { 1124 for (size_t i = 0; i < connections_.size(); ++i) {
1111 if (connections_[i]->write_state() != Connection::STATE_WRITE_TIMEOUT) { 1125 if (connections_[i]->write_state() != Connection::STATE_WRITE_TIMEOUT) {
1112 all_connections_timedout = false; 1126 all_connections_timedout = false;
1113 break; 1127 break;
1114 } 1128 }
1115 } 1129 }
1116 1130
1117 // Now update the writable state of the channel with the information we have 1131 // Now update the writable state of the channel with the information we have
1118 // so far. 1132 // so far.
1119 if (all_connections_timedout) { 1133 if (all_connections_timedout) {
1120 HandleAllTimedOut(); 1134 HandleAllTimedOut();
1121 } 1135 }
1122 1136
1123 // Update the state of this channel. This method is called whenever the 1137 // Update the state of this channel. This method is called whenever the
1124 // state of any connection changes, so this is a good place to do this. 1138 // state of any connection changes, so this is a good place to do this.
1125 UpdateState(); 1139 UpdateState();
1126 } 1140 }
1127 1141
1128 Connection* P2PTransportChannel::best_nominated_connection() const { 1142 Connection* P2PTransportChannel::selected_nominated_connection() const {
pthatcher1 2016/06/21 07:16:53 Since this is only called once, I suggest we inlin
honghaiz3 2016/06/22 08:03:16 Done.
1129 return (best_connection_ && best_connection_->nominated()) ? best_connection_ 1143 return (selected_connection_ && selected_connection_->nominated())
1130 : nullptr; 1144 ? selected_connection_
1145 : nullptr;
1131 } 1146 }
1132 1147
1133 void P2PTransportChannel::PruneConnections() { 1148 void P2PTransportChannel::PruneConnections() {
1134 // We can prune any connection for which there is a connected, writable 1149 // We can prune any connection for which there is a connected, writable
1135 // connection on the same network with better or equal priority. We leave 1150 // connection on the same network with better or equal priority. We leave
1136 // those with better priority just in case they become writable later (at 1151 // those with better priority just in case they become writable later (at
1137 // which point, we would prune out the current best connection). We leave 1152 // which point, we would prune out the current selected connection). We leave
1138 // connections on other networks because they may not be using the same 1153 // connections on other networks because they may not be using the same
1139 // resources and they may represent very distinct paths over which we can 1154 // resources and they may represent very distinct paths over which we can
1140 // switch. If the |premier| connection is not connected, we may be 1155 // switch. If the |premier| connection is not connected, we may be
1141 // reconnecting a TCP connection and temporarily do not prune connections in 1156 // reconnecting a TCP connection and temporarily do not prune connections in
1142 // this network. See the big comment in CompareConnections. 1157 // this network. See the big comment in CompareConnections.
1143 1158
1144 // Get a list of the networks that we are using. 1159 // Get a list of the networks that we are using.
1145 std::set<rtc::Network*> networks; 1160 std::set<rtc::Network*> networks;
1146 for (const Connection* conn : connections_) { 1161 for (const Connection* conn : connections_) {
1147 networks.insert(conn->port()->Network()); 1162 networks.insert(conn->port()->Network());
1148 } 1163 }
1149 for (rtc::Network* network : networks) { 1164 for (rtc::Network* network : networks) {
1150 Connection* premier = GetBestConnectionOnNetwork(network); 1165 Connection* premier = GetBestConnectionOnNetwork(network);
1151 // Do not prune connections if the current best connection is weak on this 1166 // Do not prune connections if the current selected connection is weak on
1152 // network. Otherwise, it may delete connections prematurely. 1167 // this network. Otherwise, it may delete connections prematurely.
1153 if (!premier || premier->weak()) { 1168 if (!premier || premier->weak()) {
1154 continue; 1169 continue;
1155 } 1170 }
1156 1171
1157 for (Connection* conn : connections_) { 1172 for (Connection* conn : connections_) {
1158 if ((conn != premier) && (conn->port()->Network() == network) && 1173 if ((conn != premier) && (conn->port()->Network() == network) &&
1159 (CompareConnectionCandidates(premier, conn) >= 0)) { 1174 (CompareConnectionsBase(premier, conn) >= 0)) {
Taylor Brandstetter 2016/06/21 18:33:25 Why can't you just use CompareConnections here? Is
pthatcher1 2016/06/22 06:36:33 I think this is so we don't prune a better candida
honghaiz3 2016/06/22 08:03:16 Done. I just use the CompareConnectionCandidates t
honghaiz3 2016/06/22 08:03:16 CompareConnections (now CompareConnectionsIncludin
Taylor Brandstetter 2016/06/22 16:12:22 Ah yes, that's obvious now, my mistake.
1160 conn->Prune(); 1175 conn->Prune();
1161 } 1176 }
1162 } 1177 }
1163 } 1178 }
1164 } 1179 }
1165 1180
1166 // Track the best connection, and let listeners know 1181 // Track the selected connection, and let listeners know.
Taylor Brandstetter 2016/06/21 18:33:25 Maybe "Change the" instead of "Track the".
honghaiz3 2016/06/22 08:03:16 Done.
1167 void P2PTransportChannel::SwitchBestConnectionTo(Connection* conn) { 1182 void P2PTransportChannel::SwitchSelectedConnection(Connection* conn) {
1168 // Note: if conn is NULL, the previous best_connection_ has been destroyed, 1183 // Note: if conn is NULL, the previous |selected_connection_| has been
1169 // so don't use it. 1184 // destroyed, so don't use it.
1170 Connection* old_best_connection = best_connection_; 1185 Connection* old_selected_connection = selected_connection_;
1171 best_connection_ = conn; 1186 selected_connection_ = conn;
1172 if (best_connection_) { 1187 if (selected_connection_) {
1173 if (old_best_connection) { 1188 if (old_selected_connection) {
1174 LOG_J(LS_INFO, this) << "Previous best connection: " 1189 LOG_J(LS_INFO, this) << "Previous selected connection: "
1175 << old_best_connection->ToString(); 1190 << old_selected_connection->ToString();
1176 } 1191 }
1177 LOG_J(LS_INFO, this) << "New best connection: " 1192 LOG_J(LS_INFO, this) << "New selected connection: "
1178 << best_connection_->ToString(); 1193 << selected_connection_->ToString();
1179 SignalRouteChange(this, best_connection_->remote_candidate()); 1194 SignalRouteChange(this, selected_connection_->remote_candidate());
1180 // This is a temporary, but safe fix to webrtc issue 5705. 1195 // This is a temporary, but safe fix to webrtc issue 5705.
1181 // TODO(honghaiz): Make all EWOULDBLOCK error routed through the transport 1196 // TODO(honghaiz): Make all EWOULDBLOCK error routed through the transport
1182 // channel so that it knows whether the media channel is allowed to 1197 // channel so that it knows whether the media channel is allowed to
1183 // send; then it will only signal ready-to-send if the media channel 1198 // send; then it will only signal ready-to-send if the media channel
1184 // has been disallowed to send. 1199 // has been disallowed to send.
1185 if (best_connection_->writable()) { 1200 if (selected_connection_->writable()) {
1186 SignalReadyToSend(this); 1201 SignalReadyToSend(this);
1187 } 1202 }
1188 } else { 1203 } else {
1189 LOG_J(LS_INFO, this) << "No best connection"; 1204 LOG_J(LS_INFO, this) << "No selected connection";
1190 } 1205 }
1191 // TODO(honghaiz): rename best_connection_ with selected_connection_ or 1206 // TODO(honghaiz): rename selected_connection_ with selected_connection_ or
1192 // selected_candidate pair_. 1207 // selected_candidate pair_.
1193 SignalSelectedCandidatePairChanged(this, best_connection_, 1208 SignalSelectedCandidatePairChanged(this, selected_connection_,
1194 last_sent_packet_id_); 1209 last_sent_packet_id_);
1195 } 1210 }
1196 1211
1197 // Warning: UpdateState should eventually be called whenever a connection 1212 // Warning: UpdateState should eventually be called whenever a connection
1198 // is added, deleted, or the write state of any connection changes so that the 1213 // is added, deleted, or the write state of any connection changes so that the
1199 // transport controller will get the up-to-date channel state. However it 1214 // transport controller will get the up-to-date channel state. However it
1200 // should not be called too often; in the case that multiple connection states 1215 // should not be called too often; in the case that multiple connection states
1201 // change, it should be called after all the connection states have changed. For 1216 // change, it should be called after all the connection states have changed. For
1202 // example, we call this at the end of SortConnections. 1217 // example, we call this at the end of SortConnections.
1203 void P2PTransportChannel::UpdateState() { 1218 void P2PTransportChannel::UpdateState() {
(...skipping 26 matching lines...) Expand all
1230 RTC_DCHECK(state == STATE_CONNECTING || state == STATE_COMPLETED); 1245 RTC_DCHECK(state == STATE_CONNECTING || state == STATE_COMPLETED);
1231 break; 1246 break;
1232 default: 1247 default:
1233 RTC_DCHECK(false); 1248 RTC_DCHECK(false);
1234 break; 1249 break;
1235 } 1250 }
1236 state_ = state; 1251 state_ = state;
1237 SignalStateChanged(this); 1252 SignalStateChanged(this);
1238 } 1253 }
1239 1254
1240 bool writable = best_connection_ && best_connection_->writable(); 1255 bool writable = selected_connection_ && selected_connection_->writable();
1241 set_writable(writable); 1256 set_writable(writable);
1242 1257
1243 bool receiving = false; 1258 bool receiving = false;
1244 for (const Connection* connection : connections_) { 1259 for (const Connection* connection : connections_) {
1245 if (connection->receiving()) { 1260 if (connection->receiving()) {
1246 receiving = true; 1261 receiving = true;
1247 break; 1262 break;
1248 } 1263 }
1249 } 1264 }
1250 set_receiving(receiving); 1265 set_receiving(receiving);
(...skipping 19 matching lines...) Expand all
1270 } 1285 }
1271 1286
1272 // If all connections timed out, delete them all. 1287 // If all connections timed out, delete them all.
1273 void P2PTransportChannel::HandleAllTimedOut() { 1288 void P2PTransportChannel::HandleAllTimedOut() {
1274 for (Connection* connection : connections_) { 1289 for (Connection* connection : connections_) {
1275 connection->Destroy(); 1290 connection->Destroy();
1276 } 1291 }
1277 } 1292 }
1278 1293
1279 bool P2PTransportChannel::weak() const { 1294 bool P2PTransportChannel::weak() const {
1280 return !best_connection_ || best_connection_->weak(); 1295 return !selected_connection_ || selected_connection_->weak();
1281 } 1296 }
1282 1297
1283 // If we have a best connection, return it, otherwise return top one in the 1298 // If we have a selected connection, return it, otherwise return top one in the
1284 // list (later we will mark it best). 1299 // list (later we will mark it best).
1285 Connection* P2PTransportChannel::GetBestConnectionOnNetwork( 1300 Connection* P2PTransportChannel::GetBestConnectionOnNetwork(
1286 rtc::Network* network) const { 1301 rtc::Network* network) const {
1287 // If the best connection is on this network, then it wins. 1302 // If the selected connection is on this network, then it wins.
1288 if (best_connection_ && (best_connection_->port()->Network() == network)) 1303 if (selected_connection_ &&
1289 return best_connection_; 1304 (selected_connection_->port()->Network() == network))
Taylor Brandstetter 2016/06/21 18:33:25 Nit: As long as you're changing this code, can you
honghaiz3 2016/06/22 08:03:16 Done.
1305 return selected_connection_;
1290 1306
1291 // Otherwise, we return the top-most in sorted order. 1307 // Otherwise, we return the top-most in sorted order.
1292 for (size_t i = 0; i < connections_.size(); ++i) { 1308 for (size_t i = 0; i < connections_.size(); ++i) {
1293 if (connections_[i]->port()->Network() == network) 1309 if (connections_[i]->port()->Network() == network)
1294 return connections_[i]; 1310 return connections_[i];
1295 } 1311 }
1296 1312
1297 return NULL; 1313 return NULL;
1298 } 1314 }
1299 1315
(...skipping 16 matching lines...) Expand all
1316 void P2PTransportChannel::OnSort() { 1332 void P2PTransportChannel::OnSort() {
1317 // Resort the connections based on the new statistics. 1333 // Resort the connections based on the new statistics.
1318 SortConnections(); 1334 SortConnections();
1319 } 1335 }
1320 1336
1321 // Handle queued up check-and-ping request 1337 // Handle queued up check-and-ping request
1322 void P2PTransportChannel::OnCheckAndPing() { 1338 void P2PTransportChannel::OnCheckAndPing() {
1323 // Make sure the states of the connections are up-to-date (since this affects 1339 // Make sure the states of the connections are up-to-date (since this affects
1324 // which ones are pingable). 1340 // which ones are pingable).
1325 UpdateConnectionStates(); 1341 UpdateConnectionStates();
1326 // When the best connection is not receiving or not writable, or any active 1342 // When the selected connection is not receiving or not writable, or any
1327 // connection has not been pinged enough times, use the weak ping interval. 1343 // active connection has not been pinged enough times, use the weak ping
1344 // interval.
1328 bool need_more_pings_at_weak_interval = std::any_of( 1345 bool need_more_pings_at_weak_interval = std::any_of(
1329 connections_.begin(), connections_.end(), [](Connection* conn) { 1346 connections_.begin(), connections_.end(), [](Connection* conn) {
1330 return conn->active() && 1347 return conn->active() &&
1331 conn->num_pings_sent() < MIN_PINGS_AT_WEAK_PING_INTERVAL; 1348 conn->num_pings_sent() < MIN_PINGS_AT_WEAK_PING_INTERVAL;
1332 }); 1349 });
1333 int ping_interval = (weak() || need_more_pings_at_weak_interval) 1350 int ping_interval = (weak() || need_more_pings_at_weak_interval)
1334 ? weak_ping_interval_ 1351 ? weak_ping_interval_
1335 : STRONG_PING_INTERVAL; 1352 : STRONG_PING_INTERVAL;
1336 if (rtc::TimeMillis() >= last_ping_sent_ms_ + ping_interval) { 1353 if (rtc::TimeMillis() >= last_ping_sent_ms_ + ping_interval) {
1337 Connection* conn = FindNextPingableConnection(); 1354 Connection* conn = FindNextPingableConnection();
1338 if (conn) { 1355 if (conn) {
1339 PingConnection(conn); 1356 PingConnection(conn);
1340 MarkConnectionPinged(conn); 1357 MarkConnectionPinged(conn);
1341 } 1358 }
1342 } 1359 }
1343 int delay = std::min(ping_interval, check_receiving_interval_); 1360 int delay = std::min(ping_interval, check_receiving_interval_);
1344 thread()->PostDelayed(RTC_FROM_HERE, delay, this, MSG_CHECK_AND_PING); 1361 thread()->PostDelayed(RTC_FROM_HERE, delay, this, MSG_CHECK_AND_PING);
1345 } 1362 }
1346 1363
1347 // A connection is considered a backup connection if the channel state 1364 // A connection is considered a backup connection if the channel state
1348 // is completed, the connection is not the best connection and it is active. 1365 // is completed, the connection is not the selected connection and it is active.
1349 bool P2PTransportChannel::IsBackupConnection(Connection* conn) const { 1366 bool P2PTransportChannel::IsBackupConnection(Connection* conn) const {
1350 return state_ == STATE_COMPLETED && conn != best_connection_ && 1367 return state_ == STATE_COMPLETED && conn != selected_connection_ &&
1351 conn->active(); 1368 conn->active();
1352 } 1369 }
1353 1370
1354 // Is the connection in a state for us to even consider pinging the other side? 1371 // Is the connection in a state for us to even consider pinging the other side?
1355 // We consider a connection pingable even if it's not connected because that's 1372 // We consider a connection pingable even if it's not connected because that's
1356 // how a TCP connection is kicked into reconnecting on the active side. 1373 // how a TCP connection is kicked into reconnecting on the active side.
1357 bool P2PTransportChannel::IsPingable(Connection* conn, int64_t now) { 1374 bool P2PTransportChannel::IsPingable(Connection* conn, int64_t now) {
1358 const Candidate& remote = conn->remote_candidate(); 1375 const Candidate& remote = conn->remote_candidate();
1359 // We should never get this far with an empty remote ufrag. 1376 // We should never get this far with an empty remote ufrag.
1360 ASSERT(!remote.username().empty()); 1377 ASSERT(!remote.username().empty());
(...skipping 19 matching lines...) Expand all
1380 if (IsBackupConnection(conn)) { 1397 if (IsBackupConnection(conn)) {
1381 return (now >= conn->last_ping_response_received() + 1398 return (now >= conn->last_ping_response_received() +
1382 config_.backup_connection_ping_interval); 1399 config_.backup_connection_ping_interval);
1383 } 1400 }
1384 return conn->active(); 1401 return conn->active();
1385 } 1402 }
1386 1403
1387 // Returns the next pingable connection to ping. This will be the oldest 1404 // Returns the next pingable connection to ping. This will be the oldest
1388 // pingable connection unless we have a connected, writable connection that is 1405 // pingable connection unless we have a connected, writable connection that is
1389 // past the maximum acceptable ping interval. When reconnecting a TCP 1406 // past the maximum acceptable ping interval. When reconnecting a TCP
1390 // connection, the best connection is disconnected, although still WRITABLE 1407 // connection, the selected connection is disconnected, although still WRITABLE
1391 // while reconnecting. The newly created connection should be selected as the 1408 // while reconnecting. The newly created connection should be selected as the
1392 // ping target to become writable instead. See the big comment in 1409 // ping target to become writable instead. See the big comment in
1393 // CompareConnections. 1410 // CompareConnections.
1394 Connection* P2PTransportChannel::FindNextPingableConnection() { 1411 Connection* P2PTransportChannel::FindNextPingableConnection() {
1395 int64_t now = rtc::TimeMillis(); 1412 int64_t now = rtc::TimeMillis();
1396 Connection* conn_to_ping = nullptr; 1413 Connection* conn_to_ping = nullptr;
1397 if (best_connection_ && best_connection_->connected() && 1414 if (selected_connection_ && selected_connection_->connected() &&
1398 best_connection_->writable() && 1415 selected_connection_->writable() &&
1399 (best_connection_->last_ping_sent() + config_.max_strong_interval <= 1416 (selected_connection_->last_ping_sent() + config_.max_strong_interval <=
1400 now)) { 1417 now)) {
1401 conn_to_ping = best_connection_; 1418 conn_to_ping = selected_connection_;
1402 } else { 1419 } else {
1403 conn_to_ping = FindConnectionToPing(now); 1420 conn_to_ping = FindConnectionToPing(now);
1404 } 1421 }
1405 return conn_to_ping; 1422 return conn_to_ping;
1406 } 1423 }
1407 1424
1408 void P2PTransportChannel::MarkConnectionPinged(Connection* conn) { 1425 void P2PTransportChannel::MarkConnectionPinged(Connection* conn) {
1409 if (conn && pinged_connections_.insert(conn).second) { 1426 if (conn && pinged_connections_.insert(conn).second) {
1410 unpinged_connections_.erase(conn); 1427 unpinged_connections_.erase(conn);
1411 } 1428 }
1412 } 1429 }
1413 1430
1414 // Apart from sending ping from |conn| this method also updates 1431 // Apart from sending ping from |conn| this method also updates
1415 // |use_candidate_attr| flag. The criteria to update this flag is 1432 // |use_candidate_attr| flag. The criteria to update this flag is
1416 // explained below. 1433 // explained below.
1417 // Set USE-CANDIDATE if doing ICE AND this channel is in CONTROLLING AND 1434 // Set USE-CANDIDATE if doing ICE AND this channel is in CONTROLLING AND
1418 // a) Channel is in FULL ICE AND 1435 // a) Channel is in FULL ICE AND
1419 // a.1) |conn| is the best connection OR 1436 // a.1) |conn| is the selected connection OR
1420 // a.2) there is no best connection OR 1437 // a.2) there is no selected connection OR
1421 // a.3) the best connection is unwritable OR 1438 // a.3) the selected connection is unwritable OR
1422 // a.4) |conn| has higher priority than best_connection. 1439 // a.4) |conn| has higher priority than selected_connection.
1423 // b) we're doing LITE ICE AND 1440 // b) we're doing LITE ICE AND
1424 // b.1) |conn| is the best_connection AND 1441 // b.1) |conn| is the selected_connection AND
1425 // b.2) |conn| is writable. 1442 // b.2) |conn| is writable.
1426 void P2PTransportChannel::PingConnection(Connection* conn) { 1443 void P2PTransportChannel::PingConnection(Connection* conn) {
1427 bool use_candidate = false; 1444 bool use_candidate = false;
1428 if (remote_ice_mode_ == ICEMODE_FULL && ice_role_ == ICEROLE_CONTROLLING) { 1445 if (remote_ice_mode_ == ICEMODE_FULL && ice_role_ == ICEROLE_CONTROLLING) {
1429 use_candidate = (conn == best_connection_) || (best_connection_ == NULL) || 1446 use_candidate =
1430 (!best_connection_->writable()) || 1447 (conn == selected_connection_) || (selected_connection_ == NULL) ||
1431 (CompareConnectionCandidates(best_connection_, conn) < 0); 1448 (!selected_connection_->writable()) ||
1432 } else if (remote_ice_mode_ == ICEMODE_LITE && conn == best_connection_) { 1449 (CompareConnectionCandidates(selected_connection_, conn) < 0);
1433 use_candidate = best_connection_->writable(); 1450 } else if (remote_ice_mode_ == ICEMODE_LITE && conn == selected_connection_) {
1451 use_candidate = selected_connection_->writable();
1434 } 1452 }
1435 conn->set_use_candidate_attr(use_candidate); 1453 conn->set_use_candidate_attr(use_candidate);
1436 last_ping_sent_ms_ = rtc::TimeMillis(); 1454 last_ping_sent_ms_ = rtc::TimeMillis();
1437 conn->Ping(last_ping_sent_ms_); 1455 conn->Ping(last_ping_sent_ms_);
1438 } 1456 }
1439 1457
1440 // When a connection's state changes, we need to figure out who to use as 1458 // When a connection's state changes, we need to figure out who to use as
1441 // the best connection again. It could have become usable, or become unusable. 1459 // the selected connection again. It could have become usable, or become
1460 // unusable.
1442 void P2PTransportChannel::OnConnectionStateChange(Connection* connection) { 1461 void P2PTransportChannel::OnConnectionStateChange(Connection* connection) {
1443 ASSERT(worker_thread_ == rtc::Thread::Current()); 1462 ASSERT(worker_thread_ == rtc::Thread::Current());
1444 1463
1445 // Update the best connection if the state change is from pending best
1446 // connection and role is controlled.
1447 if (ice_role_ == ICEROLE_CONTROLLED) {
1448 if (connection == pending_best_connection_ && connection->writable()) {
1449 pending_best_connection_ = NULL;
1450 LOG(LS_INFO) << "Switching best connection on controlled side"
1451 << " because it's now writable: " << connection->ToString();
1452 SwitchBestConnectionTo(connection);
1453 }
1454 }
1455
1456 // May stop the allocator session when at least one connection becomes 1464 // May stop the allocator session when at least one connection becomes
1457 // strongly connected after starting to get ports and the local candidate of 1465 // strongly connected after starting to get ports and the local candidate of
1458 // the connection is at the latest generation. It is not enough to check 1466 // the connection is at the latest generation. It is not enough to check
1459 // that the connection becomes weakly connected because the connection may be 1467 // that the connection becomes weakly connected because the connection may be
1460 // changing from (writable, receiving) to (writable, not receiving). 1468 // changing from (writable, receiving) to (writable, not receiving).
1461 bool strongly_connected = !connection->weak(); 1469 bool strongly_connected = !connection->weak();
1462 bool latest_generation = connection->local_candidate().generation() >= 1470 bool latest_generation = connection->local_candidate().generation() >=
1463 allocator_session()->generation(); 1471 allocator_session()->generation();
1464 if (strongly_connected && latest_generation) { 1472 if (strongly_connected && latest_generation) {
1465 MaybeStopPortAllocatorSessions(); 1473 MaybeStopPortAllocatorSessions();
1466 } 1474 }
1467 1475
1468 // We have to unroll the stack before doing this because we may be changing 1476 // We have to unroll the stack before doing this because we may be changing
1469 // the state of connections while sorting. 1477 // the state of connections while sorting.
1470 RequestSort(); 1478 RequestSort();
1471 } 1479 }
1472 1480
1473 // When a connection is removed, edit it out, and then update our best 1481 // When a connection is removed, edit it out, and then update our best
1474 // connection. 1482 // connection.
1475 void P2PTransportChannel::OnConnectionDestroyed(Connection* connection) { 1483 void P2PTransportChannel::OnConnectionDestroyed(Connection* connection) {
1476 ASSERT(worker_thread_ == rtc::Thread::Current()); 1484 ASSERT(worker_thread_ == rtc::Thread::Current());
1477 1485
1478 // Note: the previous best_connection_ may be destroyed by now, so don't 1486 // Note: the previous selected_connection_ may be destroyed by now, so don't
1479 // use it. 1487 // use it.
1480 1488
1481 // Remove this connection from the list. 1489 // Remove this connection from the list.
1482 std::vector<Connection*>::iterator iter = 1490 std::vector<Connection*>::iterator iter =
1483 std::find(connections_.begin(), connections_.end(), connection); 1491 std::find(connections_.begin(), connections_.end(), connection);
1484 ASSERT(iter != connections_.end()); 1492 ASSERT(iter != connections_.end());
1485 pinged_connections_.erase(*iter); 1493 pinged_connections_.erase(*iter);
1486 unpinged_connections_.erase(*iter); 1494 unpinged_connections_.erase(*iter);
1487 connections_.erase(iter); 1495 connections_.erase(iter);
1488 1496
1489 LOG_J(LS_INFO, this) << "Removed connection (" 1497 LOG_J(LS_INFO, this) << "Removed connection ("
1490 << static_cast<int>(connections_.size()) << " remaining)"; 1498 << static_cast<int>(connections_.size()) << " remaining)";
1491 1499
1492 if (pending_best_connection_ == connection) { 1500 // If this is currently the selected connection, then we need to pick a new
1493 pending_best_connection_ = NULL; 1501 // one. The call to SortConnections will pick a new one. It looks at the
1494 } 1502 // current selected connection in order to avoid switching between fairly
1495 1503 // similar ones. Since this connection is no longer an option, we can just
1496 // If this is currently the best connection, then we need to pick a new one. 1504 // set selected to nullptr and re-choose a best assuming that there was no
1497 // The call to SortConnections will pick a new one. It looks at the current 1505 // selected connection.
1498 // best connection in order to avoid switching between fairly similar ones. 1506 if (selected_connection_ == connection) {
1499 // Since this connection is no longer an option, we can just set best to NULL 1507 LOG(LS_INFO) << "selected connection destroyed. Will choose a new one.";
1500 // and re-choose a best assuming that there was no best connection. 1508 SwitchSelectedConnection(nullptr);
1501 if (best_connection_ == connection) {
1502 LOG(LS_INFO) << "Best connection destroyed. Will choose a new one.";
1503 SwitchBestConnectionTo(NULL);
1504 RequestSort(); 1509 RequestSort();
1505 } 1510 }
1506 1511
1507 UpdateState(); 1512 UpdateState();
1508 } 1513 }
1509 1514
1510 // When a port is destroyed remove it from our list of ports to use for 1515 // When a port is destroyed remove it from our list of ports to use for
1511 // connection attempts. 1516 // connection attempts.
1512 void P2PTransportChannel::OnPortDestroyed(PortInterface* port) { 1517 void P2PTransportChannel::OnPortDestroyed(PortInterface* port) {
1513 ASSERT(worker_thread_ == rtc::Thread::Current()); 1518 ASSERT(worker_thread_ == rtc::Thread::Current());
(...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after
1552 1557
1553 // Do not deliver, if packet doesn't belong to the correct transport channel. 1558 // Do not deliver, if packet doesn't belong to the correct transport channel.
1554 if (!FindConnection(connection)) 1559 if (!FindConnection(connection))
1555 return; 1560 return;
1556 1561
1557 // Let the client know of an incoming packet 1562 // Let the client know of an incoming packet
1558 SignalReadPacket(this, data, len, packet_time, 0); 1563 SignalReadPacket(this, data, len, packet_time, 0);
1559 1564
1560 // May need to switch the sending connection based on the receiving media path 1565 // May need to switch the sending connection based on the receiving media path
1561 // if this is the controlled side. 1566 // if this is the controlled side.
1562 if (ice_role_ == ICEROLE_CONTROLLED && !best_nominated_connection() && 1567 if (ice_role_ != ICEROLE_CONTROLLED || selected_connection_ == connection) {
1563 connection->writable() && best_connection_ != connection) { 1568 return;
1564 SwitchBestConnectionTo(connection); 1569 }
1570
1571 if (ShouldSwitchConnection(connection)) {
pthatcher1 2016/06/21 07:16:53 Can you move this line into ShouldSwitchConnection
honghaiz3 2016/06/22 08:03:16 Done.
1572 LOG(LS_INFO)
1573 << "Switching selected connection on controlled side due to receiving: "
1574 << connection->ToString();
1575 SwitchSelectedConnection(connection);
1565 } 1576 }
1566 } 1577 }
1567 1578
1568 void P2PTransportChannel::OnSentPacket(const rtc::SentPacket& sent_packet) { 1579 void P2PTransportChannel::OnSentPacket(const rtc::SentPacket& sent_packet) {
1569 ASSERT(worker_thread_ == rtc::Thread::Current()); 1580 ASSERT(worker_thread_ == rtc::Thread::Current());
1570 1581
1571 SignalSentPacket(this, sent_packet); 1582 SignalSentPacket(this, sent_packet);
1572 } 1583 }
1573 1584
1574 void P2PTransportChannel::OnReadyToSend(Connection* connection) { 1585 void P2PTransportChannel::OnReadyToSend(Connection* connection) {
1575 if (connection == best_connection_ && writable()) { 1586 if (connection == selected_connection_ && writable()) {
1576 SignalReadyToSend(this); 1587 SignalReadyToSend(this);
1577 } 1588 }
1578 } 1589 }
1579 1590
1580 // Find "triggered checks". We ping first those connections that have 1591 // Find "triggered checks". We ping first those connections that have
1581 // received a ping but have not sent a ping since receiving it 1592 // received a ping but have not sent a ping since receiving it
1582 // (last_received_ping > last_sent_ping). But we shouldn't do 1593 // (last_received_ping > last_sent_ping). But we shouldn't do
1583 // triggered checks if the connection is already writable. 1594 // triggered checks if the connection is already writable.
1584 Connection* P2PTransportChannel::FindOldestConnectionNeedingTriggeredCheck( 1595 Connection* P2PTransportChannel::FindOldestConnectionNeedingTriggeredCheck(
1585 int64_t now) { 1596 int64_t now) {
(...skipping 102 matching lines...) Expand 10 before | Expand all | Expand 10 after
1688 1699
1689 // During the initial state when nothing has been pinged yet, return the first 1700 // During the initial state when nothing has been pinged yet, return the first
1690 // one in the ordered |connections_|. 1701 // one in the ordered |connections_|.
1691 return *(std::find_if(connections_.begin(), connections_.end(), 1702 return *(std::find_if(connections_.begin(), connections_.end(),
1692 [conn1, conn2](Connection* conn) { 1703 [conn1, conn2](Connection* conn) {
1693 return conn == conn1 || conn == conn2; 1704 return conn == conn1 || conn == conn2;
1694 })); 1705 }));
1695 } 1706 }
1696 1707
1697 } // namespace cricket 1708 } // namespace cricket
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698