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

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: address Taylor's comments 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 // Writable connections are pinged at a faster rate while stabilizing. 148 // Writable connections are pinged at a faster rate while stabilizing.
221 const int STABILIZING_WRITABLE_CONNECTION_PING_INTERVAL = 900; // ms 149 const int STABILIZING_WRITABLE_CONNECTION_PING_INTERVAL = 900; // ms
222 150
223 // Writable connections are pinged at a slower rate once stabilized. 151 // Writable connections are pinged at a slower rate once stabilized.
224 const int STABLE_WRITABLE_CONNECTION_PING_INTERVAL = 2500; // ms 152 const int STABLE_WRITABLE_CONNECTION_PING_INTERVAL = 2500; // ms
225 153
226 static const int MIN_CHECK_RECEIVING_INTERVAL = 50; // ms 154 static const int MIN_CHECK_RECEIVING_INTERVAL = 50; // ms
227 155
228 P2PTransportChannel::P2PTransportChannel(const std::string& transport_name, 156 P2PTransportChannel::P2PTransportChannel(const std::string& transport_name,
229 int component, 157 int component,
230 P2PTransport* transport, 158 P2PTransport* transport,
231 PortAllocator* allocator) 159 PortAllocator* allocator)
232 : P2PTransportChannel(transport_name, component, allocator) {} 160 : P2PTransportChannel(transport_name, component, allocator) {}
233 161
234 P2PTransportChannel::P2PTransportChannel(const std::string& transport_name, 162 P2PTransportChannel::P2PTransportChannel(const std::string& transport_name,
235 int component, 163 int component,
236 PortAllocator* allocator) 164 PortAllocator* allocator)
237 : TransportChannelImpl(transport_name, component), 165 : TransportChannelImpl(transport_name, component),
238 allocator_(allocator), 166 allocator_(allocator),
239 worker_thread_(rtc::Thread::Current()), 167 worker_thread_(rtc::Thread::Current()),
240 incoming_only_(false), 168 incoming_only_(false),
241 error_(0), 169 error_(0),
242 best_connection_(NULL),
243 pending_best_connection_(NULL),
244 sort_dirty_(false), 170 sort_dirty_(false),
245 remote_ice_mode_(ICEMODE_FULL), 171 remote_ice_mode_(ICEMODE_FULL),
246 ice_role_(ICEROLE_UNKNOWN), 172 ice_role_(ICEROLE_UNKNOWN),
247 tiebreaker_(0), 173 tiebreaker_(0),
248 gathering_state_(kIceGatheringNew), 174 gathering_state_(kIceGatheringNew),
249 check_receiving_interval_(MIN_CHECK_RECEIVING_INTERVAL * 5), 175 check_receiving_interval_(MIN_CHECK_RECEIVING_INTERVAL * 5),
250 config_(MIN_CHECK_RECEIVING_INTERVAL * 50 /* receiving_timeout */, 176 config_(MIN_CHECK_RECEIVING_INTERVAL * 50 /* receiving_timeout */,
251 0 /* backup_connection_ping_interval */, 177 0 /* backup_connection_ping_interval */,
252 false /* gather_continually */, 178 false /* gather_continually */,
253 false /* prioritize_most_likely_candidate_pairs */, 179 false /* prioritize_most_likely_candidate_pairs */,
(...skipping 42 matching lines...) Expand 10 before | Expand all | Expand 10 after
296 connection->SignalReadyToSend.connect( 222 connection->SignalReadyToSend.connect(
297 this, &P2PTransportChannel::OnReadyToSend); 223 this, &P2PTransportChannel::OnReadyToSend);
298 connection->SignalStateChange.connect( 224 connection->SignalStateChange.connect(
299 this, &P2PTransportChannel::OnConnectionStateChange); 225 this, &P2PTransportChannel::OnConnectionStateChange);
300 connection->SignalDestroyed.connect( 226 connection->SignalDestroyed.connect(
301 this, &P2PTransportChannel::OnConnectionDestroyed); 227 this, &P2PTransportChannel::OnConnectionDestroyed);
302 connection->SignalNominated.connect(this, &P2PTransportChannel::OnNominated); 228 connection->SignalNominated.connect(this, &P2PTransportChannel::OnNominated);
303 had_connection_ = true; 229 had_connection_ = true;
304 } 230 }
305 231
232 int P2PTransportChannel::CompareConnections(
233 const cricket::Connection* a,
234 const cricket::Connection* b) const {
235 RTC_CHECK(a != nullptr);
236 RTC_CHECK(b != nullptr);
237
238 // We prefer to switch to a writable and receiving connection over a
239 // non-writable or non-receiving connection, even if the latter has
240 // been nominated by the controlling side.
241 int state_cmp = CompareConnectionStates(a, b);
242 if (state_cmp != 0) {
243 return state_cmp;
244 }
245
246 if (ice_role_ == cricket::ICEROLE_CONTROLLED) {
247 // Compare the connections based on the nomination states and the last data
248 // received time if this is on the controlled side.
249 if (a->nominated() != b->nominated()) {
250 return b->nominated() ? -1 : 1;
251 }
pthatcher1 2016/06/22 19:18:37 Can you make this match the style Taylor had in hi
honghaiz3 2016/06/22 20:01:23 We should do this when we merge the two CLs, so we
252
253 if (a->last_data_received() > b->last_data_received()) {
254 return 1;
255 }
256 if (a->last_data_received() < b->last_data_received()) {
257 return -1;
258 }
259 }
260
261 // Compare the network cost and priority.
262 return CompareConnectionCandidates(a, b);
263 }
264
265 // Determines whether we should switch the selected connection to
266 // |new_connection| based the writable/receiving state, the nomination state,
267 // and the last data received time. This prevents the controlled side from
268 // switching the selected connection too frequently when the controlling side
269 // is doing aggressive nominations. The precedence of the connection switching
270 // criteria is as follows:
271 // i) write/receiving/connected states
272 // ii) For controlled side,
273 // a) nomination state,
274 // b) last data received time.
275 // iii) Lower cost / higher priority.
276 // iv) rtt.
277 // TODO(honghaiz): Stop the aggressive nomination on the controlling side and
278 // implement the ice-renomination option.
279 bool P2PTransportChannel::ShouldSwitchSelectedConnection(
280 cricket::Connection* new_connection) const {
281 if (!new_connection || selected_connection_ == new_connection) {
282 return false;
283 }
284
285 if (selected_connection_ == nullptr) {
286 return true;
287 }
288
289 int cmp = CompareConnections(selected_connection_, new_connection);
290 if (cmp != 0) {
291 return cmp < 0;
292 }
293
294 // If everything else is the same, switch only if rtt has improved by
295 // a margin.
296 return new_connection->rtt() <= selected_connection_->rtt() - kMinImprovement;
297 }
298
306 void P2PTransportChannel::SetIceRole(IceRole ice_role) { 299 void P2PTransportChannel::SetIceRole(IceRole ice_role) {
307 ASSERT(worker_thread_ == rtc::Thread::Current()); 300 ASSERT(worker_thread_ == rtc::Thread::Current());
308 if (ice_role_ != ice_role) { 301 if (ice_role_ != ice_role) {
309 ice_role_ = ice_role; 302 ice_role_ = ice_role;
310 for (PortInterface* port : ports_) { 303 for (PortInterface* port : ports_) {
311 port->SetIceRole(ice_role); 304 port->SetIceRole(ice_role);
312 } 305 }
313 // Update role on removed ports as well, because they may still have 306 // Update role on removed ports as well, because they may still have
314 // connections alive that should be using the correct role. 307 // connections alive that should be using the correct role.
315 for (PortInterface* port : removed_ports_) { 308 for (PortInterface* port : removed_ports_) {
(...skipping 414 matching lines...) Expand 10 before | Expand all | Expand 10 after
730 return nullptr; 723 return nullptr;
731 } 724 }
732 *generation = params.rend() - it - 1; 725 *generation = params.rend() - it - 1;
733 return &(*it); 726 return &(*it);
734 } 727 }
735 728
736 void P2PTransportChannel::OnNominated(Connection* conn) { 729 void P2PTransportChannel::OnNominated(Connection* conn) {
737 ASSERT(worker_thread_ == rtc::Thread::Current()); 730 ASSERT(worker_thread_ == rtc::Thread::Current());
738 ASSERT(ice_role_ == ICEROLE_CONTROLLED); 731 ASSERT(ice_role_ == ICEROLE_CONTROLLED);
739 732
740 if (conn->write_state() == Connection::STATE_WRITABLE) { 733 if (selected_connection_ == conn) {
741 if (best_connection_ != conn) { 734 return;
742 pending_best_connection_ = NULL;
743 LOG(LS_INFO) << "Switching best connection on controlled side: "
744 << conn->ToString();
745 SwitchBestConnectionTo(conn);
746 // Now we have selected the best connection, time to prune other existing
747 // connections and update the read/write state of the channel.
748 RequestSort();
749 }
750 } else {
751 LOG(LS_INFO) << "Not switching the best connection on controlled side yet,"
752 << " because it's not writable: " << conn->ToString();
753 pending_best_connection_ = conn;
754 } 735 }
736
737 if (!ShouldSwitchSelectedConnection(conn)) {
738 LOG(LS_INFO)
739 << "Not switching the selected connection on controlled side yet: "
740 << conn->ToString();
741 return;
742 }
743
744 LOG(LS_INFO)
745 << "Switching selected connection on controlled side due to nomination: "
746 << conn->ToString();
747 SwitchSelectedConnection(conn);
748 // Now that we have selected a connection, it is time to prune other
749 // connections and update the read/write state of the channel.
750 RequestSort();
755 } 751 }
756 752
757 void P2PTransportChannel::AddRemoteCandidate(const Candidate& candidate) { 753 void P2PTransportChannel::AddRemoteCandidate(const Candidate& candidate) {
758 ASSERT(worker_thread_ == rtc::Thread::Current()); 754 ASSERT(worker_thread_ == rtc::Thread::Current());
759 755
760 uint32_t generation = GetRemoteCandidateGeneration(candidate); 756 uint32_t generation = GetRemoteCandidateGeneration(candidate);
761 // If a remote candidate with a previous generation arrives, drop it. 757 // If a remote candidate with a previous generation arrives, drop it.
762 if (generation < remote_ice_generation()) { 758 if (generation < remote_ice_generation()) {
763 LOG(LS_WARNING) << "Dropping a remote candidate because its ufrag " 759 LOG(LS_WARNING) << "Dropping a remote candidate because its ufrag "
764 << candidate.username() 760 << candidate.username()
(...skipping 229 matching lines...) Expand 10 before | Expand all | Expand 10 after
994 ASSERT(worker_thread_ == rtc::Thread::Current()); 990 ASSERT(worker_thread_ == rtc::Thread::Current());
995 991
996 const auto& found = options_.find(opt); 992 const auto& found = options_.find(opt);
997 if (found == options_.end()) { 993 if (found == options_.end()) {
998 return false; 994 return false;
999 } 995 }
1000 *value = found->second; 996 *value = found->second;
1001 return true; 997 return true;
1002 } 998 }
1003 999
1004 // Send data to the other side, using our best connection. 1000 // Send data to the other side, using our selected connection.
1005 int P2PTransportChannel::SendPacket(const char *data, size_t len, 1001 int P2PTransportChannel::SendPacket(const char *data, size_t len,
1006 const rtc::PacketOptions& options, 1002 const rtc::PacketOptions& options,
1007 int flags) { 1003 int flags) {
1008 ASSERT(worker_thread_ == rtc::Thread::Current()); 1004 ASSERT(worker_thread_ == rtc::Thread::Current());
1009 if (flags != 0) { 1005 if (flags != 0) {
1010 error_ = EINVAL; 1006 error_ = EINVAL;
1011 return -1; 1007 return -1;
1012 } 1008 }
1013 if (best_connection_ == NULL) { 1009 if (selected_connection_ == NULL) {
1014 error_ = EWOULDBLOCK; 1010 error_ = EWOULDBLOCK;
1015 return -1; 1011 return -1;
1016 } 1012 }
1017 1013
1018 last_sent_packet_id_ = options.packet_id; 1014 last_sent_packet_id_ = options.packet_id;
1019 int sent = best_connection_->Send(data, len, options); 1015 int sent = selected_connection_->Send(data, len, options);
1020 if (sent <= 0) { 1016 if (sent <= 0) {
1021 ASSERT(sent < 0); 1017 ASSERT(sent < 0);
1022 error_ = best_connection_->GetError(); 1018 error_ = selected_connection_->GetError();
1023 } 1019 }
1024 return sent; 1020 return sent;
1025 } 1021 }
1026 1022
1027 bool P2PTransportChannel::GetStats(ConnectionInfos *infos) { 1023 bool P2PTransportChannel::GetStats(ConnectionInfos *infos) {
1028 ASSERT(worker_thread_ == rtc::Thread::Current()); 1024 ASSERT(worker_thread_ == rtc::Thread::Current());
1029 // Gather connection infos. 1025 // Gather connection infos.
1030 infos->clear(); 1026 infos->clear();
1031 1027
1032 for (Connection* connection : connections_) { 1028 for (Connection* connection : connections_) {
1033 ConnectionInfo info = connection->stats(); 1029 ConnectionInfo info = connection->stats();
1034 info.best_connection = (best_connection_ == connection); 1030 info.best_connection = (selected_connection_ == connection);
1035 info.receiving = connection->receiving(); 1031 info.receiving = connection->receiving();
1036 info.writable = (connection->write_state() == Connection::STATE_WRITABLE); 1032 info.writable = (connection->write_state() == Connection::STATE_WRITABLE);
1037 info.timeout = 1033 info.timeout =
1038 (connection->write_state() == Connection::STATE_WRITE_TIMEOUT); 1034 (connection->write_state() == Connection::STATE_WRITE_TIMEOUT);
1039 info.new_connection = !connection->reported(); 1035 info.new_connection = !connection->reported();
1040 connection->set_reported(true); 1036 connection->set_reported(true);
1041 info.rtt = connection->rtt(); 1037 info.rtt = connection->rtt();
1042 info.local_candidate = connection->local_candidate(); 1038 info.local_candidate = connection->local_candidate();
1043 info.remote_candidate = connection->remote_candidate(); 1039 info.remote_candidate = connection->remote_candidate();
1044 info.key = connection; 1040 info.key = connection;
(...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after
1083 // will be sorted. 1079 // will be sorted.
1084 UpdateConnectionStates(); 1080 UpdateConnectionStates();
1085 1081
1086 // Any changes after this point will require a re-sort. 1082 // Any changes after this point will require a re-sort.
1087 sort_dirty_ = false; 1083 sort_dirty_ = false;
1088 1084
1089 // Find the best alternative connection by sorting. It is important to note 1085 // Find the best alternative connection by sorting. It is important to note
1090 // that amongst equal preference, writable connections, this will choose the 1086 // that amongst equal preference, writable connections, this will choose the
1091 // one whose estimated latency is lowest. So it is the only one that we 1087 // one whose estimated latency is lowest. So it is the only one that we
1092 // need to consider switching to. 1088 // need to consider switching to.
1093 ConnectionCompare cmp; 1089 std::stable_sort(
1094 std::stable_sort(connections_.begin(), connections_.end(), cmp); 1090 connections_.begin(), connections_.end(),
1091 [this](const cricket::Connection* a, const cricket::Connection* b) {
1092 int cmp = CompareConnections(a, b);
1093 if (cmp != 0) {
1094 return cmp > 0;
1095 }
1096
1097 // Otherwise, sort based on latency estimate.
1098 return a->rtt() < b->rtt();
1099 });
1095 LOG(LS_VERBOSE) << "Sorting " << connections_.size() 1100 LOG(LS_VERBOSE) << "Sorting " << connections_.size()
1096 << " available connections:"; 1101 << " available connections:";
1097 for (size_t i = 0; i < connections_.size(); ++i) { 1102 for (size_t i = 0; i < connections_.size(); ++i) {
1098 LOG(LS_VERBOSE) << connections_[i]->ToString(); 1103 LOG(LS_VERBOSE) << connections_[i]->ToString();
1099 } 1104 }
1100 1105
1101 Connection* top_connection = 1106 Connection* top_connection =
1102 (connections_.size() > 0) ? connections_[0] : nullptr; 1107 (connections_.size() > 0) ? connections_[0] : nullptr;
1103 1108
1104 // If necessary, switch to the new choice. 1109 // If necessary, switch to the new choice. Note that |top_connection| doesn't
1105 // Note that |top_connection| doesn't have to be writable to become the best 1110 // have to be writable to become the selected connection although it will
1106 // connection although it will have higher priority if it is writable. 1111 // have higher priority if it is writable.
1107 if (ShouldSwitch(best_connection_, top_connection, ice_role_)) { 1112 if (ShouldSwitchSelectedConnection(top_connection)) {
1108 LOG(LS_INFO) << "Switching best connection: " << top_connection->ToString(); 1113 LOG(LS_INFO) << "Switching selected connection after sorting: "
1109 SwitchBestConnectionTo(top_connection); 1114 << top_connection->ToString();
1115 SwitchSelectedConnection(top_connection);
1110 } 1116 }
1111 1117
1112 // Controlled side can prune only if the best connection has been nominated. 1118 // The controlled side can prune only if the selected connection has been
1113 // because otherwise it may delete the connection that will be selected by 1119 // nominated because otherwise it may prune the connection that will be
1114 // the controlling side. 1120 // selected by the controlling side.
1115 if (ice_role_ == ICEROLE_CONTROLLING || best_nominated_connection()) { 1121 // TODO(honghaiz): This is not enough to prevent a connection from being
1122 // pruned too early because with aggressive nomination, the controlling side
1123 // will nominate every connection until it becomes writable. What we do now
1124 // is to un-prune a connection if a ping request comes with a nomination, or
1125 // new data is received on a nominated connection.
1126 if (ice_role_ == ICEROLE_CONTROLLING ||
1127 (selected_connection_ && selected_connection_->nominated())) {
1116 PruneConnections(); 1128 PruneConnections();
1117 } 1129 }
1118 1130
1119 // Check if all connections are timedout. 1131 // Check if all connections are timedout.
1120 bool all_connections_timedout = true; 1132 bool all_connections_timedout = true;
1121 for (size_t i = 0; i < connections_.size(); ++i) { 1133 for (size_t i = 0; i < connections_.size(); ++i) {
1122 if (connections_[i]->write_state() != Connection::STATE_WRITE_TIMEOUT) { 1134 if (connections_[i]->write_state() != Connection::STATE_WRITE_TIMEOUT) {
1123 all_connections_timedout = false; 1135 all_connections_timedout = false;
1124 break; 1136 break;
1125 } 1137 }
1126 } 1138 }
1127 1139
1128 // Now update the writable state of the channel with the information we have 1140 // Now update the writable state of the channel with the information we have
1129 // so far. 1141 // so far.
1130 if (all_connections_timedout) { 1142 if (all_connections_timedout) {
1131 HandleAllTimedOut(); 1143 HandleAllTimedOut();
1132 } 1144 }
1133 1145
1134 // Update the state of this channel. This method is called whenever the 1146 // Update the state of this channel. This method is called whenever the
1135 // state of any connection changes, so this is a good place to do this. 1147 // state of any connection changes, so this is a good place to do this.
1136 UpdateState(); 1148 UpdateState();
1137 } 1149 }
1138 1150
1139 Connection* P2PTransportChannel::best_nominated_connection() const {
1140 return (best_connection_ && best_connection_->nominated()) ? best_connection_
1141 : nullptr;
1142 }
1143
1144 void P2PTransportChannel::PruneConnections() { 1151 void P2PTransportChannel::PruneConnections() {
1145 // We can prune any connection for which there is a connected, writable 1152 // We can prune any connection for which there is a connected, writable
1146 // connection on the same network with better or equal priority. We leave 1153 // connection on the same network with better or equal priority. We leave
1147 // those with better priority just in case they become writable later (at 1154 // those with better priority just in case they become writable later (at
1148 // which point, we would prune out the current best connection). We leave 1155 // which point, we would prune out the current selected connection). We leave
1149 // connections on other networks because they may not be using the same 1156 // connections on other networks because they may not be using the same
1150 // resources and they may represent very distinct paths over which we can 1157 // resources and they may represent very distinct paths over which we can
1151 // switch. If the |premier| connection is not connected, we may be 1158 // switch. If the |premier| connection is not connected, we may be
1152 // reconnecting a TCP connection and temporarily do not prune connections in 1159 // reconnecting a TCP connection and temporarily do not prune connections in
1153 // this network. See the big comment in CompareConnections. 1160 // this network. See the big comment in CompareConnectionStates.
1154 1161
1155 // Get a list of the networks that we are using. 1162 // Get a list of the networks that we are using.
1156 std::set<rtc::Network*> networks; 1163 std::set<rtc::Network*> networks;
1157 for (const Connection* conn : connections_) { 1164 for (const Connection* conn : connections_) {
1158 networks.insert(conn->port()->Network()); 1165 networks.insert(conn->port()->Network());
1159 } 1166 }
1160 for (rtc::Network* network : networks) { 1167 for (rtc::Network* network : networks) {
1161 Connection* premier = GetBestConnectionOnNetwork(network); 1168 Connection* premier = GetBestConnectionOnNetwork(network);
1162 // Do not prune connections if the current best connection is weak on this 1169 // Do not prune connections if the current selected connection is weak on
1163 // network. Otherwise, it may delete connections prematurely. 1170 // this network. Otherwise, it may delete connections prematurely.
1164 if (!premier || premier->weak()) { 1171 if (!premier || premier->weak()) {
1165 continue; 1172 continue;
1166 } 1173 }
1167 1174
1168 for (Connection* conn : connections_) { 1175 for (Connection* conn : connections_) {
1169 if ((conn != premier) && (conn->port()->Network() == network) && 1176 if ((conn != premier) && (conn->port()->Network() == network) &&
1170 (CompareConnectionCandidates(premier, conn) >= 0)) { 1177 (CompareConnectionCandidates(premier, conn) >= 0)) {
1171 conn->Prune(); 1178 conn->Prune();
1172 } 1179 }
1173 } 1180 }
1174 } 1181 }
1175 } 1182 }
1176 1183
1177 // Track the best connection, and let listeners know 1184 // Change the selected connection, and let listeners know.
1178 void P2PTransportChannel::SwitchBestConnectionTo(Connection* conn) { 1185 void P2PTransportChannel::SwitchSelectedConnection(Connection* conn) {
1179 // Note: if conn is NULL, the previous best_connection_ has been destroyed, 1186 // Note: if conn is NULL, the previous |selected_connection_| has been
1180 // so don't use it. 1187 // destroyed, so don't use it.
1181 Connection* old_best_connection = best_connection_; 1188 Connection* old_selected_connection = selected_connection_;
1182 best_connection_ = conn; 1189 selected_connection_ = conn;
1183 if (best_connection_) { 1190 if (selected_connection_) {
1184 if (old_best_connection) { 1191 if (old_selected_connection) {
1185 LOG_J(LS_INFO, this) << "Previous best connection: " 1192 LOG_J(LS_INFO, this) << "Previous selected connection: "
1186 << old_best_connection->ToString(); 1193 << old_selected_connection->ToString();
1187 } 1194 }
1188 LOG_J(LS_INFO, this) << "New best connection: " 1195 LOG_J(LS_INFO, this) << "New selected connection: "
1189 << best_connection_->ToString(); 1196 << selected_connection_->ToString();
1190 SignalRouteChange(this, best_connection_->remote_candidate()); 1197 SignalRouteChange(this, selected_connection_->remote_candidate());
1191 // This is a temporary, but safe fix to webrtc issue 5705. 1198 // This is a temporary, but safe fix to webrtc issue 5705.
1192 // TODO(honghaiz): Make all EWOULDBLOCK error routed through the transport 1199 // TODO(honghaiz): Make all EWOULDBLOCK error routed through the transport
1193 // channel so that it knows whether the media channel is allowed to 1200 // channel so that it knows whether the media channel is allowed to
1194 // send; then it will only signal ready-to-send if the media channel 1201 // send; then it will only signal ready-to-send if the media channel
1195 // has been disallowed to send. 1202 // has been disallowed to send.
1196 if (best_connection_->writable()) { 1203 if (selected_connection_->writable()) {
1197 SignalReadyToSend(this); 1204 SignalReadyToSend(this);
1198 } 1205 }
1199 } else { 1206 } else {
1200 LOG_J(LS_INFO, this) << "No best connection"; 1207 LOG_J(LS_INFO, this) << "No selected connection";
1201 } 1208 }
1202 // TODO(honghaiz): rename best_connection_ with selected_connection_ or 1209 SignalSelectedCandidatePairChanged(this, selected_connection_,
1203 // selected_candidate pair_.
1204 SignalSelectedCandidatePairChanged(this, best_connection_,
1205 last_sent_packet_id_); 1210 last_sent_packet_id_);
1206 } 1211 }
1207 1212
1208 // Warning: UpdateState should eventually be called whenever a connection 1213 // Warning: UpdateState should eventually be called whenever a connection
1209 // is added, deleted, or the write state of any connection changes so that the 1214 // is added, deleted, or the write state of any connection changes so that the
1210 // transport controller will get the up-to-date channel state. However it 1215 // transport controller will get the up-to-date channel state. However it
1211 // should not be called too often; in the case that multiple connection states 1216 // should not be called too often; in the case that multiple connection states
1212 // change, it should be called after all the connection states have changed. For 1217 // change, it should be called after all the connection states have changed. For
1213 // example, we call this at the end of SortConnections. 1218 // example, we call this at the end of SortConnections.
1214 void P2PTransportChannel::UpdateState() { 1219 void P2PTransportChannel::UpdateState() {
(...skipping 26 matching lines...) Expand all
1241 RTC_DCHECK(state == STATE_CONNECTING || state == STATE_COMPLETED); 1246 RTC_DCHECK(state == STATE_CONNECTING || state == STATE_COMPLETED);
1242 break; 1247 break;
1243 default: 1248 default:
1244 RTC_DCHECK(false); 1249 RTC_DCHECK(false);
1245 break; 1250 break;
1246 } 1251 }
1247 state_ = state; 1252 state_ = state;
1248 SignalStateChanged(this); 1253 SignalStateChanged(this);
1249 } 1254 }
1250 1255
1251 bool writable = best_connection_ && best_connection_->writable(); 1256 bool writable = selected_connection_ && selected_connection_->writable();
1252 set_writable(writable); 1257 set_writable(writable);
1253 1258
1254 bool receiving = false; 1259 bool receiving = false;
1255 for (const Connection* connection : connections_) { 1260 for (const Connection* connection : connections_) {
1256 if (connection->receiving()) { 1261 if (connection->receiving()) {
1257 receiving = true; 1262 receiving = true;
1258 break; 1263 break;
1259 } 1264 }
1260 } 1265 }
1261 set_receiving(receiving); 1266 set_receiving(receiving);
(...skipping 19 matching lines...) Expand all
1281 } 1286 }
1282 1287
1283 // If all connections timed out, delete them all. 1288 // If all connections timed out, delete them all.
1284 void P2PTransportChannel::HandleAllTimedOut() { 1289 void P2PTransportChannel::HandleAllTimedOut() {
1285 for (Connection* connection : connections_) { 1290 for (Connection* connection : connections_) {
1286 connection->Destroy(); 1291 connection->Destroy();
1287 } 1292 }
1288 } 1293 }
1289 1294
1290 bool P2PTransportChannel::weak() const { 1295 bool P2PTransportChannel::weak() const {
1291 return !best_connection_ || best_connection_->weak(); 1296 return !selected_connection_ || selected_connection_->weak();
1292 } 1297 }
1293 1298
1294 // If we have a best connection, return it, otherwise return top one in the 1299 // If we have a selected connection, return it, otherwise return top one in the
1295 // list (later we will mark it best). 1300 // list (later we will mark it best).
1296 Connection* P2PTransportChannel::GetBestConnectionOnNetwork( 1301 Connection* P2PTransportChannel::GetBestConnectionOnNetwork(
1297 rtc::Network* network) const { 1302 rtc::Network* network) const {
1298 // If the best connection is on this network, then it wins. 1303 // If the selected connection is on this network, then it wins.
1299 if (best_connection_ && (best_connection_->port()->Network() == network)) 1304 if (selected_connection_ &&
1300 return best_connection_; 1305 (selected_connection_->port()->Network() == network)) {
1306 return selected_connection_;
1307 }
1301 1308
1302 // Otherwise, we return the top-most in sorted order. 1309 // Otherwise, we return the top-most in sorted order.
1303 for (size_t i = 0; i < connections_.size(); ++i) { 1310 for (size_t i = 0; i < connections_.size(); ++i) {
1304 if (connections_[i]->port()->Network() == network) 1311 if (connections_[i]->port()->Network() == network) {
1305 return connections_[i]; 1312 return connections_[i];
1313 }
1306 } 1314 }
1307 1315
1308 return NULL; 1316 return NULL;
1309 } 1317 }
1310 1318
1311 // Handle any queued up requests 1319 // Handle any queued up requests
1312 void P2PTransportChannel::OnMessage(rtc::Message *pmsg) { 1320 void P2PTransportChannel::OnMessage(rtc::Message *pmsg) {
1313 switch (pmsg->message_id) { 1321 switch (pmsg->message_id) {
1314 case MSG_SORT: 1322 case MSG_SORT:
1315 OnSort(); 1323 OnSort();
(...skipping 11 matching lines...) Expand all
1327 void P2PTransportChannel::OnSort() { 1335 void P2PTransportChannel::OnSort() {
1328 // Resort the connections based on the new statistics. 1336 // Resort the connections based on the new statistics.
1329 SortConnections(); 1337 SortConnections();
1330 } 1338 }
1331 1339
1332 // Handle queued up check-and-ping request 1340 // Handle queued up check-and-ping request
1333 void P2PTransportChannel::OnCheckAndPing() { 1341 void P2PTransportChannel::OnCheckAndPing() {
1334 // Make sure the states of the connections are up-to-date (since this affects 1342 // Make sure the states of the connections are up-to-date (since this affects
1335 // which ones are pingable). 1343 // which ones are pingable).
1336 UpdateConnectionStates(); 1344 UpdateConnectionStates();
1337 // When the best connection is not receiving or not writable, or any active 1345 // When the selected connection is not receiving or not writable, or any
1338 // connection has not been pinged enough times, use the weak ping interval. 1346 // active connection has not been pinged enough times, use the weak ping
1347 // interval.
1339 bool need_more_pings_at_weak_interval = std::any_of( 1348 bool need_more_pings_at_weak_interval = std::any_of(
1340 connections_.begin(), connections_.end(), [](Connection* conn) { 1349 connections_.begin(), connections_.end(), [](Connection* conn) {
1341 return conn->active() && 1350 return conn->active() &&
1342 conn->num_pings_sent() < MIN_PINGS_AT_WEAK_PING_INTERVAL; 1351 conn->num_pings_sent() < MIN_PINGS_AT_WEAK_PING_INTERVAL;
1343 }); 1352 });
1344 int ping_interval = (weak() || need_more_pings_at_weak_interval) 1353 int ping_interval = (weak() || need_more_pings_at_weak_interval)
1345 ? weak_ping_interval_ 1354 ? weak_ping_interval_
1346 : STRONG_PING_INTERVAL; 1355 : STRONG_PING_INTERVAL;
1347 if (rtc::TimeMillis() >= last_ping_sent_ms_ + ping_interval) { 1356 if (rtc::TimeMillis() >= last_ping_sent_ms_ + ping_interval) {
1348 Connection* conn = FindNextPingableConnection(); 1357 Connection* conn = FindNextPingableConnection();
1349 if (conn) { 1358 if (conn) {
1350 PingConnection(conn); 1359 PingConnection(conn);
1351 MarkConnectionPinged(conn); 1360 MarkConnectionPinged(conn);
1352 } 1361 }
1353 } 1362 }
1354 int delay = std::min(ping_interval, check_receiving_interval_); 1363 int delay = std::min(ping_interval, check_receiving_interval_);
1355 thread()->PostDelayed(RTC_FROM_HERE, delay, this, MSG_CHECK_AND_PING); 1364 thread()->PostDelayed(RTC_FROM_HERE, delay, this, MSG_CHECK_AND_PING);
1356 } 1365 }
1357 1366
1358 // A connection is considered a backup connection if the channel state 1367 // A connection is considered a backup connection if the channel state
1359 // is completed, the connection is not the best connection and it is active. 1368 // is completed, the connection is not the selected connection and it is active.
1360 bool P2PTransportChannel::IsBackupConnection(Connection* conn) const { 1369 bool P2PTransportChannel::IsBackupConnection(Connection* conn) const {
1361 return state_ == STATE_COMPLETED && conn != best_connection_ && 1370 return state_ == STATE_COMPLETED && conn != selected_connection_ &&
1362 conn->active(); 1371 conn->active();
1363 } 1372 }
1364 1373
1365 // Is the connection in a state for us to even consider pinging the other side? 1374 // Is the connection in a state for us to even consider pinging the other side?
1366 // We consider a connection pingable even if it's not connected because that's 1375 // We consider a connection pingable even if it's not connected because that's
1367 // how a TCP connection is kicked into reconnecting on the active side. 1376 // how a TCP connection is kicked into reconnecting on the active side.
1368 bool P2PTransportChannel::IsPingable(Connection* conn, int64_t now) { 1377 bool P2PTransportChannel::IsPingable(Connection* conn, int64_t now) {
1369 const Candidate& remote = conn->remote_candidate(); 1378 const Candidate& remote = conn->remote_candidate();
1370 // We should never get this far with an empty remote ufrag. 1379 // We should never get this far with an empty remote ufrag.
1371 ASSERT(!remote.username().empty()); 1380 ASSERT(!remote.username().empty());
(...skipping 29 matching lines...) Expand all
1401 if (!conn->writable()) { 1410 if (!conn->writable()) {
1402 return true; 1411 return true;
1403 } 1412 }
1404 1413
1405 // Ping writable, active connections if it's been long enough since the last 1414 // Ping writable, active connections if it's been long enough since the last
1406 // ping. 1415 // ping.
1407 int ping_interval = CalculateActiveWritablePingInterval(conn, now); 1416 int ping_interval = CalculateActiveWritablePingInterval(conn, now);
1408 return (now >= conn->last_ping_sent() + ping_interval); 1417 return (now >= conn->last_ping_sent() + ping_interval);
1409 } 1418 }
1410 1419
1411 bool P2PTransportChannel::IsBestConnectionPingable(int64_t now) { 1420 bool P2PTransportChannel::IsSelectedConnectionPingable(int64_t now) {
1412 if (!best_connection_ || !best_connection_->connected() || 1421 if (!selected_connection_ || !selected_connection_->connected() ||
1413 !best_connection_->writable()) { 1422 !selected_connection_->writable()) {
1414 return false; 1423 return false;
1415 } 1424 }
1416 1425
1417 int interval = CalculateActiveWritablePingInterval(best_connection_, now); 1426 int interval = CalculateActiveWritablePingInterval(selected_connection_, now);
1418 return best_connection_->last_ping_sent() + interval <= now; 1427 return selected_connection_->last_ping_sent() + interval <= now;
1419 } 1428 }
1420 1429
1421 int P2PTransportChannel::CalculateActiveWritablePingInterval(Connection* conn, 1430 int P2PTransportChannel::CalculateActiveWritablePingInterval(Connection* conn,
1422 int64_t now) { 1431 int64_t now) {
1423 // Ping each connection at a higher rate at least 1432 // Ping each connection at a higher rate at least
1424 // MIN_PINGS_AT_WEAK_PING_INTERVAL times. 1433 // MIN_PINGS_AT_WEAK_PING_INTERVAL times.
1425 if (conn->num_pings_sent() < MIN_PINGS_AT_WEAK_PING_INTERVAL) { 1434 if (conn->num_pings_sent() < MIN_PINGS_AT_WEAK_PING_INTERVAL) {
1426 return weak_ping_interval_; 1435 return weak_ping_interval_;
1427 } 1436 }
1428 1437
1429 int stable_interval = config_.stable_writable_connection_ping_interval; 1438 int stable_interval = config_.stable_writable_connection_ping_interval;
1430 int stablizing_interval = 1439 int stablizing_interval =
1431 std::min(stable_interval, STABILIZING_WRITABLE_CONNECTION_PING_INTERVAL); 1440 std::min(stable_interval, STABILIZING_WRITABLE_CONNECTION_PING_INTERVAL);
1432 1441
1433 return conn->stable(now) ? stable_interval : stablizing_interval; 1442 return conn->stable(now) ? stable_interval : stablizing_interval;
1434 } 1443 }
1435 1444
1436 // Returns the next pingable connection to ping. This will be the oldest 1445 // Returns the next pingable connection to ping. This will be the oldest
1437 // pingable connection unless we have a connected, writable connection that is 1446 // pingable connection unless we have a connected, writable connection that is
1438 // past the writable ping interval. When reconnecting a TCP 1447 // past the writable ping interval. When reconnecting a TCP
1439 // connection, the best connection is disconnected, although still WRITABLE 1448 // connection, the selected connection is disconnected, although still WRITABLE
1440 // while reconnecting. The newly created connection should be selected as the 1449 // while reconnecting. The newly created connection should be selected as the
1441 // ping target to become writable instead. See the big comment in 1450 // ping target to become writable instead. See the big comment in
1442 // CompareConnections. 1451 // CompareConnectionStates.
1443 Connection* P2PTransportChannel::FindNextPingableConnection() { 1452 Connection* P2PTransportChannel::FindNextPingableConnection() {
1444 int64_t now = rtc::TimeMillis(); 1453 int64_t now = rtc::TimeMillis();
1445 Connection* conn_to_ping = nullptr; 1454 Connection* conn_to_ping = nullptr;
1446 if (IsBestConnectionPingable(now)) { 1455 if (IsSelectedConnectionPingable(now)) {
1447 conn_to_ping = best_connection_; 1456 conn_to_ping = selected_connection_;
1448 } else { 1457 } else {
1449 conn_to_ping = FindConnectionToPing(now); 1458 conn_to_ping = FindConnectionToPing(now);
1450 } 1459 }
1451 return conn_to_ping; 1460 return conn_to_ping;
1452 } 1461 }
1453 1462
1454 void P2PTransportChannel::MarkConnectionPinged(Connection* conn) { 1463 void P2PTransportChannel::MarkConnectionPinged(Connection* conn) {
1455 if (conn && pinged_connections_.insert(conn).second) { 1464 if (conn && pinged_connections_.insert(conn).second) {
1456 unpinged_connections_.erase(conn); 1465 unpinged_connections_.erase(conn);
1457 } 1466 }
1458 } 1467 }
1459 1468
1460 // Apart from sending ping from |conn| this method also updates 1469 // Apart from sending ping from |conn| this method also updates
1461 // |use_candidate_attr| flag. The criteria to update this flag is 1470 // |use_candidate_attr| flag. The criteria to update this flag is
1462 // explained below. 1471 // explained below.
1463 // Set USE-CANDIDATE if doing ICE AND this channel is in CONTROLLING AND 1472 // Set USE-CANDIDATE if doing ICE AND this channel is in CONTROLLING AND
1464 // a) Channel is in FULL ICE AND 1473 // a) Channel is in FULL ICE AND
1465 // a.1) |conn| is the best connection OR 1474 // a.1) |conn| is the selected connection OR
1466 // a.2) there is no best connection OR 1475 // a.2) there is no selected connection OR
1467 // a.3) the best connection is unwritable OR 1476 // a.3) the selected connection is unwritable OR
1468 // a.4) |conn| has higher priority than best_connection. 1477 // a.4) |conn| has higher priority than selected_connection.
1469 // b) we're doing LITE ICE AND 1478 // b) we're doing LITE ICE AND
1470 // b.1) |conn| is the best_connection AND 1479 // b.1) |conn| is the selected_connection AND
1471 // b.2) |conn| is writable. 1480 // b.2) |conn| is writable.
1472 void P2PTransportChannel::PingConnection(Connection* conn) { 1481 void P2PTransportChannel::PingConnection(Connection* conn) {
1473 bool use_candidate = false; 1482 bool use_candidate = false;
1474 if (remote_ice_mode_ == ICEMODE_FULL && ice_role_ == ICEROLE_CONTROLLING) { 1483 if (remote_ice_mode_ == ICEMODE_FULL && ice_role_ == ICEROLE_CONTROLLING) {
1475 use_candidate = (conn == best_connection_) || (best_connection_ == NULL) || 1484 use_candidate =
1476 (!best_connection_->writable()) || 1485 (conn == selected_connection_) || (selected_connection_ == NULL) ||
1477 (CompareConnectionCandidates(best_connection_, conn) < 0); 1486 (!selected_connection_->writable()) ||
1478 } else if (remote_ice_mode_ == ICEMODE_LITE && conn == best_connection_) { 1487 (CompareConnectionCandidates(selected_connection_, conn) < 0);
1479 use_candidate = best_connection_->writable(); 1488 } else if (remote_ice_mode_ == ICEMODE_LITE && conn == selected_connection_) {
1489 use_candidate = selected_connection_->writable();
1480 } 1490 }
1481 conn->set_use_candidate_attr(use_candidate); 1491 conn->set_use_candidate_attr(use_candidate);
1482 last_ping_sent_ms_ = rtc::TimeMillis(); 1492 last_ping_sent_ms_ = rtc::TimeMillis();
1483 conn->Ping(last_ping_sent_ms_); 1493 conn->Ping(last_ping_sent_ms_);
1484 } 1494 }
1485 1495
1486 // When a connection's state changes, we need to figure out who to use as 1496 // When a connection's state changes, we need to figure out who to use as
1487 // the best connection again. It could have become usable, or become unusable. 1497 // the selected connection again. It could have become usable, or become
1498 // unusable.
1488 void P2PTransportChannel::OnConnectionStateChange(Connection* connection) { 1499 void P2PTransportChannel::OnConnectionStateChange(Connection* connection) {
1489 ASSERT(worker_thread_ == rtc::Thread::Current()); 1500 ASSERT(worker_thread_ == rtc::Thread::Current());
1490 1501
1491 // Update the best connection if the state change is from pending best
1492 // connection and role is controlled.
1493 if (ice_role_ == ICEROLE_CONTROLLED) {
1494 if (connection == pending_best_connection_ && connection->writable()) {
1495 pending_best_connection_ = NULL;
1496 LOG(LS_INFO) << "Switching best connection on controlled side"
1497 << " because it's now writable: " << connection->ToString();
1498 SwitchBestConnectionTo(connection);
1499 }
1500 }
1501
1502 // May stop the allocator session when at least one connection becomes 1502 // May stop the allocator session when at least one connection becomes
1503 // strongly connected after starting to get ports and the local candidate of 1503 // strongly connected after starting to get ports and the local candidate of
1504 // the connection is at the latest generation. It is not enough to check 1504 // the connection is at the latest generation. It is not enough to check
1505 // that the connection becomes weakly connected because the connection may be 1505 // that the connection becomes weakly connected because the connection may be
1506 // changing from (writable, receiving) to (writable, not receiving). 1506 // changing from (writable, receiving) to (writable, not receiving).
1507 bool strongly_connected = !connection->weak(); 1507 bool strongly_connected = !connection->weak();
1508 bool latest_generation = connection->local_candidate().generation() >= 1508 bool latest_generation = connection->local_candidate().generation() >=
1509 allocator_session()->generation(); 1509 allocator_session()->generation();
1510 if (strongly_connected && latest_generation) { 1510 if (strongly_connected && latest_generation) {
1511 MaybeStopPortAllocatorSessions(); 1511 MaybeStopPortAllocatorSessions();
1512 } 1512 }
1513 1513
1514 // We have to unroll the stack before doing this because we may be changing 1514 // We have to unroll the stack before doing this because we may be changing
1515 // the state of connections while sorting. 1515 // the state of connections while sorting.
1516 RequestSort(); 1516 RequestSort();
1517 } 1517 }
1518 1518
1519 // When a connection is removed, edit it out, and then update our best 1519 // When a connection is removed, edit it out, and then update our best
1520 // connection. 1520 // connection.
1521 void P2PTransportChannel::OnConnectionDestroyed(Connection* connection) { 1521 void P2PTransportChannel::OnConnectionDestroyed(Connection* connection) {
1522 ASSERT(worker_thread_ == rtc::Thread::Current()); 1522 ASSERT(worker_thread_ == rtc::Thread::Current());
1523 1523
1524 // Note: the previous best_connection_ may be destroyed by now, so don't 1524 // Note: the previous selected_connection_ may be destroyed by now, so don't
1525 // use it. 1525 // use it.
1526 1526
1527 // Remove this connection from the list. 1527 // Remove this connection from the list.
1528 std::vector<Connection*>::iterator iter = 1528 std::vector<Connection*>::iterator iter =
1529 std::find(connections_.begin(), connections_.end(), connection); 1529 std::find(connections_.begin(), connections_.end(), connection);
1530 ASSERT(iter != connections_.end()); 1530 ASSERT(iter != connections_.end());
1531 pinged_connections_.erase(*iter); 1531 pinged_connections_.erase(*iter);
1532 unpinged_connections_.erase(*iter); 1532 unpinged_connections_.erase(*iter);
1533 connections_.erase(iter); 1533 connections_.erase(iter);
1534 1534
1535 LOG_J(LS_INFO, this) << "Removed connection (" 1535 LOG_J(LS_INFO, this) << "Removed connection ("
1536 << static_cast<int>(connections_.size()) << " remaining)"; 1536 << static_cast<int>(connections_.size()) << " remaining)";
1537 1537
1538 if (pending_best_connection_ == connection) { 1538 // If this is currently the selected connection, then we need to pick a new
1539 pending_best_connection_ = NULL; 1539 // one. The call to SortConnections will pick a new one. It looks at the
1540 } 1540 // current selected connection in order to avoid switching between fairly
1541 1541 // similar ones. Since this connection is no longer an option, we can just
1542 // If this is currently the best connection, then we need to pick a new one. 1542 // set selected to nullptr and re-choose a best assuming that there was no
1543 // The call to SortConnections will pick a new one. It looks at the current 1543 // selected connection.
1544 // best connection in order to avoid switching between fairly similar ones. 1544 if (selected_connection_ == connection) {
1545 // Since this connection is no longer an option, we can just set best to NULL 1545 LOG(LS_INFO) << "selected connection destroyed. Will choose a new one.";
1546 // and re-choose a best assuming that there was no best connection. 1546 SwitchSelectedConnection(nullptr);
1547 if (best_connection_ == connection) {
1548 LOG(LS_INFO) << "Best connection destroyed. Will choose a new one.";
1549 SwitchBestConnectionTo(NULL);
1550 RequestSort(); 1547 RequestSort();
1551 } 1548 }
1552 1549
1553 UpdateState(); 1550 UpdateState();
1554 } 1551 }
1555 1552
1556 // When a port is destroyed remove it from our list of ports to use for 1553 // When a port is destroyed remove it from our list of ports to use for
1557 // connection attempts. 1554 // connection attempts.
1558 void P2PTransportChannel::OnPortDestroyed(PortInterface* port) { 1555 void P2PTransportChannel::OnPortDestroyed(PortInterface* port) {
1559 ASSERT(worker_thread_ == rtc::Thread::Current()); 1556 ASSERT(worker_thread_ == rtc::Thread::Current());
(...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after
1599 1596
1600 // Do not deliver, if packet doesn't belong to the correct transport channel. 1597 // Do not deliver, if packet doesn't belong to the correct transport channel.
1601 if (!FindConnection(connection)) 1598 if (!FindConnection(connection))
1602 return; 1599 return;
1603 1600
1604 // Let the client know of an incoming packet 1601 // Let the client know of an incoming packet
1605 SignalReadPacket(this, data, len, packet_time, 0); 1602 SignalReadPacket(this, data, len, packet_time, 0);
1606 1603
1607 // May need to switch the sending connection based on the receiving media path 1604 // May need to switch the sending connection based on the receiving media path
1608 // if this is the controlled side. 1605 // if this is the controlled side.
1609 if (ice_role_ == ICEROLE_CONTROLLED && !best_nominated_connection() && 1606 if (ice_role_ == ICEROLE_CONTROLLED &&
1610 connection->writable() && best_connection_ != connection) { 1607 ShouldSwitchSelectedConnection(connection)) {
1611 SwitchBestConnectionTo(connection); 1608 LOG(LS_INFO) << "Switching selected connection on controlled side due to "
1609 << "data received: " << connection->ToString();
1610 SwitchSelectedConnection(connection);
1612 } 1611 }
1613 } 1612 }
1614 1613
1615 void P2PTransportChannel::OnSentPacket(const rtc::SentPacket& sent_packet) { 1614 void P2PTransportChannel::OnSentPacket(const rtc::SentPacket& sent_packet) {
1616 ASSERT(worker_thread_ == rtc::Thread::Current()); 1615 ASSERT(worker_thread_ == rtc::Thread::Current());
1617 1616
1618 SignalSentPacket(this, sent_packet); 1617 SignalSentPacket(this, sent_packet);
1619 } 1618 }
1620 1619
1621 void P2PTransportChannel::OnReadyToSend(Connection* connection) { 1620 void P2PTransportChannel::OnReadyToSend(Connection* connection) {
1622 if (connection == best_connection_ && writable()) { 1621 if (connection == selected_connection_ && writable()) {
1623 SignalReadyToSend(this); 1622 SignalReadyToSend(this);
1624 } 1623 }
1625 } 1624 }
1626 1625
1627 // Find "triggered checks". We ping first those connections that have 1626 // Find "triggered checks". We ping first those connections that have
1628 // received a ping but have not sent a ping since receiving it 1627 // received a ping but have not sent a ping since receiving it
1629 // (last_received_ping > last_sent_ping). But we shouldn't do 1628 // (last_received_ping > last_sent_ping). But we shouldn't do
1630 // triggered checks if the connection is already writable. 1629 // triggered checks if the connection is already writable.
1631 Connection* P2PTransportChannel::FindOldestConnectionNeedingTriggeredCheck( 1630 Connection* P2PTransportChannel::FindOldestConnectionNeedingTriggeredCheck(
1632 int64_t now) { 1631 int64_t now) {
(...skipping 102 matching lines...) Expand 10 before | Expand all | Expand 10 after
1735 1734
1736 // During the initial state when nothing has been pinged yet, return the first 1735 // During the initial state when nothing has been pinged yet, return the first
1737 // one in the ordered |connections_|. 1736 // one in the ordered |connections_|.
1738 return *(std::find_if(connections_.begin(), connections_.end(), 1737 return *(std::find_if(connections_.begin(), connections_.end(),
1739 [conn1, conn2](Connection* conn) { 1738 [conn1, conn2](Connection* conn) {
1740 return conn == conn1 || conn == conn2; 1739 return conn == conn1 || conn == conn2;
1741 })); 1740 }));
1742 } 1741 }
1743 1742
1744 } // namespace cricket 1743 } // namespace cricket
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698