OLD | NEW |
---|---|
1 /* | 1 /* |
2 * Copyright 2004 The WebRTC Project Authors. All rights reserved. | 2 * Copyright 2004 The WebRTC Project Authors. All rights reserved. |
3 * | 3 * |
4 * Use of this source code is governed by a BSD-style license | 4 * Use of this source code is governed by a BSD-style license |
5 * that can be found in the LICENSE file in the root of the source | 5 * that can be found in the LICENSE file in the root of the source |
6 * tree. An additional intellectual property rights grant can be found | 6 * tree. An additional intellectual property rights grant can be found |
7 * in the file PATENTS. All contributing project authors may | 7 * in the file PATENTS. All contributing project authors may |
8 * be found in the AUTHORS file in the root of the source tree. | 8 * be found in the AUTHORS file in the root of the source tree. |
9 */ | 9 */ |
10 | 10 |
11 #include "webrtc/p2p/base/p2ptransportchannel.h" | 11 #include "webrtc/p2p/base/p2ptransportchannel.h" |
12 | 12 |
13 #include <set> | 13 #include <set> |
14 #include "webrtc/p2p/base/common.h" | 14 #include "webrtc/p2p/base/common.h" |
15 #include "webrtc/p2p/base/relayport.h" // For RELAY_PORT_TYPE. | 15 #include "webrtc/p2p/base/relayport.h" // For RELAY_PORT_TYPE. |
16 #include "webrtc/p2p/base/stunport.h" // For STUN_PORT_TYPE. | 16 #include "webrtc/p2p/base/stunport.h" // For STUN_PORT_TYPE. |
17 #include "webrtc/base/common.h" | 17 #include "webrtc/base/common.h" |
18 #include "webrtc/base/crc32.h" | 18 #include "webrtc/base/crc32.h" |
19 #include "webrtc/base/logging.h" | 19 #include "webrtc/base/logging.h" |
20 #include "webrtc/base/stringencode.h" | 20 #include "webrtc/base/stringencode.h" |
21 | 21 |
22 namespace { | 22 namespace { |
23 | 23 |
24 // messages for queuing up work for ourselves | 24 // messages for queuing up work for ourselves |
25 enum { | 25 enum { MSG_SORT = 1, MSG_CHECK_AND_PING }; |
26 MSG_SORT = 1, | |
27 MSG_PING, | |
28 MSG_CHECK_RECEIVING | |
29 }; | |
30 | 26 |
31 // When the socket is unwritable, we will use 10 Kbps (ignoring IP+UDP headers) | 27 // When the socket is unwritable, we will use 10 Kbps (ignoring IP+UDP headers) |
32 // for pinging. When the socket is writable, we will use only 1 Kbps because | 28 // for pinging. When the socket is writable, we will use only 1 Kbps because |
33 // we don't want to degrade the quality on a modem. These numbers should work | 29 // we don't want to degrade the quality on a modem. These numbers should work |
34 // well on a 28.8K modem, which is the slowest connection on which the voice | 30 // well on a 28.8K modem, which is the slowest connection on which the voice |
35 // quality is reasonable at all. | 31 // quality is reasonable at all. |
36 static const uint32 PING_PACKET_SIZE = 60 * 8; | 32 static const uint32 PING_PACKET_SIZE = 60 * 8; |
37 static const uint32 WRITABLE_DELAY = 1000 * PING_PACKET_SIZE / 1000; // 480ms | 33 // STRONG_PING_DELAY (480ms) is applied when the best connection is not |
38 static const uint32 UNWRITABLE_DELAY = 1000 * PING_PACKET_SIZE / 10000; // 50ms | 34 // writable or receiving. |
35 static const uint32 STRONG_PING_DELAY = 1000 * PING_PACKET_SIZE / 1000; | |
36 // WEAK_PING_DELAY (48ms) is applied when the best connection is both | |
37 // writable and receiving. | |
38 static const uint32 WEAK_PING_DELAY = 1000 * PING_PACKET_SIZE / 10000; | |
pthatcher1
2015/09/17 22:01:17
Are the comments backwards? I thought WEAK was fo
honghaiz3
2015/09/21 22:53:42
WEAK means SHORT and STRONG means LONG.
I feel usi
| |
39 | 39 |
40 // If there is a current writable connection, then we will also try hard to | 40 // If there is a current writable connection, then we will also try hard to |
41 // make sure it is pinged at this rate. | 41 // make sure it is pinged at this rate (a little less than |
42 static const uint32 MAX_CURRENT_WRITABLE_DELAY = 900; // 2*WRITABLE_DELAY - bit | 42 // 2 * STRONG_PING_DELAY). |
43 static const uint32 MAX_CURRENT_WRITABLE_DELAY = 900; | |
43 | 44 |
44 static const int MIN_CHECK_RECEIVING_DELAY = 50; // ms | 45 static const int MIN_CHECK_RECEIVING_DELAY = 50; // ms |
45 | 46 |
46 // The minimum improvement in RTT that justifies a switch. | 47 // The minimum improvement in RTT that justifies a switch. |
47 static const double kMinImprovement = 10; | 48 static const double kMinImprovement = 10; |
48 | 49 |
49 cricket::PortInterface::CandidateOrigin GetOrigin(cricket::PortInterface* port, | 50 cricket::PortInterface::CandidateOrigin GetOrigin(cricket::PortInterface* port, |
50 cricket::PortInterface* origin_port) { | 51 cricket::PortInterface* origin_port) { |
51 if (!origin_port) | 52 if (!origin_port) |
52 return cricket::PortInterface::ORIGIN_MESSAGE; | 53 return cricket::PortInterface::ORIGIN_MESSAGE; |
(...skipping 10 matching lines...) Expand all Loading... | |
63 if (a->priority() > b->priority()) | 64 if (a->priority() > b->priority()) |
64 return 1; | 65 return 1; |
65 if (a->priority() < b->priority()) | 66 if (a->priority() < b->priority()) |
66 return -1; | 67 return -1; |
67 | 68 |
68 // If we're still tied at this point, prefer a younger generation. | 69 // If we're still tied at this point, prefer a younger generation. |
69 return (a->remote_candidate().generation() + a->port()->generation()) - | 70 return (a->remote_candidate().generation() + a->port()->generation()) - |
70 (b->remote_candidate().generation() + b->port()->generation()); | 71 (b->remote_candidate().generation() + b->port()->generation()); |
71 } | 72 } |
72 | 73 |
73 // Compare two connections based on their connected state, writability and | 74 // Compare two connections based on their receiving, writing, and connected |
74 // static preferences. | 75 // states. |
75 int CompareConnections(cricket::Connection *a, cricket::Connection *b) { | 76 int CompareConnectionStates(cricket::Connection* a, cricket::Connection* b) { |
76 // Sort based on write-state. Better states have lower values. | 77 // Sort based on write-state. Better states have lower values. |
77 if (a->write_state() < b->write_state()) | 78 if (a->write_state() < b->write_state()) |
78 return 1; | 79 return 1; |
79 if (a->write_state() > b->write_state()) | 80 if (a->write_state() > b->write_state()) |
80 return -1; | 81 return -1; |
81 | 82 |
83 if (a->receiving() && !b->receiving()) | |
84 return 1; | |
85 if (!a->receiving() && b->receiving()) | |
86 return -1; | |
87 | |
82 // WARNING: Some complexity here about TCP reconnecting. | 88 // WARNING: Some complexity here about TCP reconnecting. |
83 // When a TCP connection fails because of a TCP socket disconnecting, the | 89 // When a TCP connection fails because of a TCP socket disconnecting, the |
84 // active side of the connection will attempt to reconnect for 5 seconds while | 90 // active side of the connection will attempt to reconnect for 5 seconds while |
85 // pretending to be writable (the connection is not set to the unwritable | 91 // pretending to be writable (the connection is not set to the unwritable |
86 // state). On the passive side, the connection also remains writable even | 92 // state). On the passive side, the connection also remains writable even |
87 // though it is disconnected, and a new connection is created when the active | 93 // though it is disconnected, and a new connection is created when the active |
88 // side connects. At that point, there are two TCP connections on the passive | 94 // side connects. At that point, there are two TCP connections on the passive |
89 // side: 1. the old, disconnected one that is pretending to be writable, and | 95 // side: 1. the old, disconnected one that is pretending to be writable, and |
90 // 2. the new, connected one that is maybe not yet writable. For purposes of | 96 // 2. the new, connected one that is maybe not yet writable. For purposes of |
91 // pruning, pinging, and selecting the best connection, we want to treat the | 97 // pruning, pinging, and selecting the best connection, we want to treat the |
(...skipping 11 matching lines...) Expand all Loading... | |
103 // the new connection, when it becomes writable, should have higher priority. | 109 // the new connection, when it becomes writable, should have higher priority. |
104 if (a->write_state() == cricket::Connection::STATE_WRITABLE && | 110 if (a->write_state() == cricket::Connection::STATE_WRITABLE && |
105 b->write_state() == cricket::Connection::STATE_WRITABLE) { | 111 b->write_state() == cricket::Connection::STATE_WRITABLE) { |
106 if (a->connected() && !b->connected()) { | 112 if (a->connected() && !b->connected()) { |
107 return 1; | 113 return 1; |
108 } | 114 } |
109 if (!a->connected() && b->connected()) { | 115 if (!a->connected() && b->connected()) { |
110 return -1; | 116 return -1; |
111 } | 117 } |
112 } | 118 } |
119 return 0; | |
120 } | |
113 | 121 |
122 int CompareConnections(cricket::Connection* a, cricket::Connection* b) { | |
123 int state_cmp = CompareConnectionStates(a, b); | |
124 if (state_cmp != 0) { | |
125 return state_cmp; | |
126 } | |
114 // Compare the candidate information. | 127 // Compare the candidate information. |
115 return CompareConnectionCandidates(a, b); | 128 return CompareConnectionCandidates(a, b); |
116 } | 129 } |
117 | 130 |
118 // Wraps the comparison connection into a less than operator that puts higher | 131 // Wraps the comparison connection into a less than operator that puts higher |
119 // priority writable connections first. | 132 // priority writable connections first. |
120 class ConnectionCompare { | 133 class ConnectionCompare { |
121 public: | 134 public: |
122 bool operator()(const cricket::Connection *ca, | 135 bool operator()(const cricket::Connection *ca, |
123 const cricket::Connection *cb) { | 136 const cricket::Connection *cb) { |
(...skipping 18 matching lines...) Expand all Loading... | |
142 // efficiency by being used bidirectionally, as opposed to two separate | 155 // efficiency by being used bidirectionally, as opposed to two separate |
143 // unidirectional streams. This test should probably occur before | 156 // unidirectional streams. This test should probably occur before |
144 // comparison of local prefs (assuming combined prefs are the same). We | 157 // comparison of local prefs (assuming combined prefs are the same). We |
145 // need to be careful though, not to bounce back and forth with both sides | 158 // need to be careful though, not to bounce back and forth with both sides |
146 // trying to rendevous with the other. | 159 // trying to rendevous with the other. |
147 } | 160 } |
148 }; | 161 }; |
149 | 162 |
150 // Determines whether we should switch between two connections, based first on | 163 // Determines whether we should switch between two connections, based first on |
151 // static preferences and then (if those are equal) on latency estimates. | 164 // static preferences and then (if those are equal) on latency estimates. |
152 bool ShouldSwitch(cricket::Connection* a_conn, cricket::Connection* b_conn) { | 165 bool ShouldSwitch(cricket::Connection* a_conn, |
166 cricket::Connection* b_conn, | |
167 cricket::IceRole ice_role) { | |
153 if (a_conn == b_conn) | 168 if (a_conn == b_conn) |
154 return false; | 169 return false; |
155 | 170 |
156 if (!a_conn || !b_conn) // don't think the latter should happen | 171 if (!a_conn || !b_conn) // don't think the latter should happen. |
157 return true; | 172 return true; |
158 | 173 |
159 int prefs_cmp = CompareConnections(a_conn, b_conn); | 174 // If the RECEIVING/WRITE/CONNECT states are different, we should switch |
160 if (prefs_cmp < 0) | 175 // regardless of the nominated state. Otherwise, do not switch if |a_conn| is |
161 return true; | 176 // nominated but |b_conn| is not. |
162 if (prefs_cmp > 0) | 177 int state_cmp = CompareConnectionStates(a_conn, b_conn); |
178 if (state_cmp != 0) { | |
179 return state_cmp < 0; | |
180 } | |
181 if (ice_role == cricket::ICEROLE_CONTROLLED && | |
182 a_conn->nominated() > b_conn->nominated()) { | |
183 LOG(LS_VERBOSE) << "Controlled side did not switch due to nominated status"; | |
163 return false; | 184 return false; |
185 } | |
186 | |
187 int prefs_cmp = CompareConnectionCandidates(a_conn, b_conn); | |
188 if (prefs_cmp != 0) { | |
189 return prefs_cmp < 0; | |
190 } | |
164 | 191 |
165 return b_conn->rtt() <= a_conn->rtt() + kMinImprovement; | 192 return b_conn->rtt() <= a_conn->rtt() + kMinImprovement; |
166 } | 193 } |
167 | 194 |
168 } // unnamed namespace | 195 } // unnamed namespace |
169 | 196 |
170 namespace cricket { | 197 namespace cricket { |
171 | 198 |
172 P2PTransportChannel::P2PTransportChannel(const std::string& content_name, | 199 P2PTransportChannel::P2PTransportChannel(const std::string& content_name, |
173 int component, | 200 int component, |
174 P2PTransport* transport, | 201 P2PTransport* transport, |
175 PortAllocator *allocator) : | 202 PortAllocator* allocator) |
176 TransportChannelImpl(content_name, component), | 203 : TransportChannelImpl(content_name, component), |
177 transport_(transport), | 204 transport_(transport), |
178 allocator_(allocator), | 205 allocator_(allocator), |
179 worker_thread_(rtc::Thread::Current()), | 206 worker_thread_(rtc::Thread::Current()), |
180 incoming_only_(false), | 207 incoming_only_(false), |
181 waiting_for_signaling_(false), | 208 waiting_for_signaling_(false), |
182 error_(0), | 209 error_(0), |
183 best_connection_(NULL), | 210 best_connection_(nullptr), |
184 pending_best_connection_(NULL), | 211 pending_best_connection_(nullptr), |
185 sort_dirty_(false), | 212 next_connection_to_ping_(nullptr), |
186 was_writable_(false), | 213 sort_dirty_(false), |
187 remote_ice_mode_(ICEMODE_FULL), | 214 was_writable_(false), |
188 ice_role_(ICEROLE_UNKNOWN), | 215 remote_ice_mode_(ICEMODE_FULL), |
189 tiebreaker_(0), | 216 ice_role_(ICEROLE_UNKNOWN), |
190 remote_candidate_generation_(0), | 217 tiebreaker_(0), |
191 check_receiving_delay_(MIN_CHECK_RECEIVING_DELAY * 5), | 218 remote_candidate_generation_(0), |
192 receiving_timeout_(MIN_CHECK_RECEIVING_DELAY * 50) { | 219 check_receiving_delay_(MIN_CHECK_RECEIVING_DELAY * 5), |
193 } | 220 receiving_timeout_(MIN_CHECK_RECEIVING_DELAY * 50), |
221 ping_delay_(WEAK_PING_DELAY), | |
222 last_ping_sent_(0) {} | |
194 | 223 |
195 P2PTransportChannel::~P2PTransportChannel() { | 224 P2PTransportChannel::~P2PTransportChannel() { |
196 ASSERT(worker_thread_ == rtc::Thread::Current()); | 225 ASSERT(worker_thread_ == rtc::Thread::Current()); |
197 | 226 |
198 for (uint32 i = 0; i < allocator_sessions_.size(); ++i) | 227 for (uint32 i = 0; i < allocator_sessions_.size(); ++i) |
199 delete allocator_sessions_[i]; | 228 delete allocator_sessions_[i]; |
200 } | 229 } |
201 | 230 |
202 // Add the allocator session to our list so that we know which sessions | 231 // Add the allocator session to our list so that we know which sessions |
203 // are still active. | 232 // are still active. |
(...skipping 10 matching lines...) Expand all Loading... | |
214 session->SignalCandidatesReady.connect( | 243 session->SignalCandidatesReady.connect( |
215 this, &P2PTransportChannel::OnCandidatesReady); | 244 this, &P2PTransportChannel::OnCandidatesReady); |
216 session->SignalCandidatesAllocationDone.connect( | 245 session->SignalCandidatesAllocationDone.connect( |
217 this, &P2PTransportChannel::OnCandidatesAllocationDone); | 246 this, &P2PTransportChannel::OnCandidatesAllocationDone); |
218 session->StartGettingPorts(); | 247 session->StartGettingPorts(); |
219 } | 248 } |
220 | 249 |
221 void P2PTransportChannel::AddConnection(Connection* connection) { | 250 void P2PTransportChannel::AddConnection(Connection* connection) { |
222 connections_.push_back(connection); | 251 connections_.push_back(connection); |
223 connection->set_remote_ice_mode(remote_ice_mode_); | 252 connection->set_remote_ice_mode(remote_ice_mode_); |
253 connection->set_receiving_timeout(receiving_timeout_); | |
224 connection->SignalReadPacket.connect( | 254 connection->SignalReadPacket.connect( |
225 this, &P2PTransportChannel::OnReadPacket); | 255 this, &P2PTransportChannel::OnReadPacket); |
226 connection->SignalReadyToSend.connect( | 256 connection->SignalReadyToSend.connect( |
227 this, &P2PTransportChannel::OnReadyToSend); | 257 this, &P2PTransportChannel::OnReadyToSend); |
228 connection->SignalStateChange.connect( | 258 connection->SignalStateChange.connect( |
229 this, &P2PTransportChannel::OnConnectionStateChange); | 259 this, &P2PTransportChannel::OnConnectionStateChange); |
230 connection->SignalDestroyed.connect( | 260 connection->SignalDestroyed.connect( |
231 this, &P2PTransportChannel::OnConnectionDestroyed); | 261 this, &P2PTransportChannel::OnConnectionDestroyed); |
232 connection->SignalNominated.connect(this, &P2PTransportChannel::OnNominated); | 262 connection->SignalNominated.connect(this, &P2PTransportChannel::OnNominated); |
233 } | 263 } |
(...skipping 14 matching lines...) Expand all Loading... | |
248 if (!ports_.empty()) { | 278 if (!ports_.empty()) { |
249 LOG(LS_ERROR) | 279 LOG(LS_ERROR) |
250 << "Attempt to change tiebreaker after Port has been allocated."; | 280 << "Attempt to change tiebreaker after Port has been allocated."; |
251 return; | 281 return; |
252 } | 282 } |
253 | 283 |
254 tiebreaker_ = tiebreaker; | 284 tiebreaker_ = tiebreaker; |
255 } | 285 } |
256 | 286 |
257 // Currently a channel is considered ICE completed once there is no | 287 // Currently a channel is considered ICE completed once there is no |
258 // more than one connection per Network. This works for a single NIC | 288 // more than one connection per Network that is not pruned. |
259 // with both IPv4 and IPv6 enabled. However, this condition won't | 289 // If all connections are pruned, declare transport failure. |
260 // happen when there are multiple NICs and all of them have | |
261 // connectivity. | |
262 // TODO(guoweis): Change Completion to be driven by a channel level | |
263 // timer. | |
264 TransportChannelState P2PTransportChannel::GetState() const { | 290 TransportChannelState P2PTransportChannel::GetState() const { |
265 std::set<rtc::Network*> networks; | 291 std::set<rtc::Network*> networks; |
pthatcher1
2015/09/17 22:01:17
This is more like networks_with_unpruned_connectio
honghaiz3
2015/09/21 22:53:42
Done.
| |
266 | 292 for (const Connection* connection : connections_) { |
267 if (connections_.size() == 0) { | 293 if (connection->pruned()) { |
268 return TransportChannelState::STATE_FAILED; | 294 continue; |
269 } | 295 } |
270 | 296 rtc::Network* network = connection->port()->Network(); |
271 for (uint32 i = 0; i < connections_.size(); ++i) { | |
272 rtc::Network* network = connections_[i]->port()->Network(); | |
273 if (networks.find(network) == networks.end()) { | 297 if (networks.find(network) == networks.end()) { |
274 networks.insert(network); | 298 networks.insert(network); |
275 } else { | 299 } else { |
276 LOG_J(LS_VERBOSE, this) << "Ice not completed yet for this channel as " | 300 LOG_J(LS_VERBOSE, this) << "Ice not completed yet for this channel as " |
277 << network->ToString() | 301 << network->ToString() |
278 << " has more than 1 connection."; | 302 << " has more than 1 connection."; |
279 return TransportChannelState::STATE_CONNECTING; | 303 return TransportChannelState::STATE_CONNECTING; |
280 } | 304 } |
281 } | 305 } |
306 if (networks.size() == 0) { | |
307 return TransportChannelState::STATE_FAILED; | |
308 } | |
309 | |
282 LOG_J(LS_VERBOSE, this) << "Ice is completed for this channel."; | 310 LOG_J(LS_VERBOSE, this) << "Ice is completed for this channel."; |
283 | |
284 return TransportChannelState::STATE_COMPLETED; | 311 return TransportChannelState::STATE_COMPLETED; |
285 } | 312 } |
286 | 313 |
287 void P2PTransportChannel::SetIceCredentials(const std::string& ice_ufrag, | 314 void P2PTransportChannel::SetIceCredentials(const std::string& ice_ufrag, |
288 const std::string& ice_pwd) { | 315 const std::string& ice_pwd) { |
289 ASSERT(worker_thread_ == rtc::Thread::Current()); | 316 ASSERT(worker_thread_ == rtc::Thread::Current()); |
290 bool ice_restart = false; | 317 bool ice_restart = false; |
291 if (!ice_ufrag_.empty() && !ice_pwd_.empty()) { | 318 if (!ice_ufrag_.empty() && !ice_pwd_.empty()) { |
292 // Restart candidate allocation if there is any change in either | 319 // Restart candidate allocation if there is any change in either |
293 // ice ufrag or password. | 320 // ice ufrag or password. |
(...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
335 | 362 |
336 void P2PTransportChannel::SetReceivingTimeout(int receiving_timeout_ms) { | 363 void P2PTransportChannel::SetReceivingTimeout(int receiving_timeout_ms) { |
337 if (receiving_timeout_ms < 0) { | 364 if (receiving_timeout_ms < 0) { |
338 return; | 365 return; |
339 } | 366 } |
340 receiving_timeout_ = receiving_timeout_ms; | 367 receiving_timeout_ = receiving_timeout_ms; |
341 check_receiving_delay_ = | 368 check_receiving_delay_ = |
342 std::max(MIN_CHECK_RECEIVING_DELAY, receiving_timeout_ / 10); | 369 std::max(MIN_CHECK_RECEIVING_DELAY, receiving_timeout_ / 10); |
343 LOG(LS_VERBOSE) << "Set ICE receiving timeout to " << receiving_timeout_ | 370 LOG(LS_VERBOSE) << "Set ICE receiving timeout to " << receiving_timeout_ |
344 << " milliseconds"; | 371 << " milliseconds"; |
372 for (Connection* connection : connections_) { | |
373 connection->set_receiving_timeout(receiving_timeout_); | |
374 } | |
345 } | 375 } |
346 | 376 |
347 // Go into the state of processing candidates, and running in general | 377 // Go into the state of processing candidates, and running in general |
348 void P2PTransportChannel::Connect() { | 378 void P2PTransportChannel::Connect() { |
349 ASSERT(worker_thread_ == rtc::Thread::Current()); | 379 ASSERT(worker_thread_ == rtc::Thread::Current()); |
350 if (ice_ufrag_.empty() || ice_pwd_.empty()) { | 380 if (ice_ufrag_.empty() || ice_pwd_.empty()) { |
351 ASSERT(false); | 381 ASSERT(false); |
352 LOG(LS_ERROR) << "P2PTransportChannel::Connect: The ice_ufrag_ and the " | 382 LOG(LS_ERROR) << "P2PTransportChannel::Connect: The ice_ufrag_ and the " |
353 << "ice_pwd_ are not set."; | 383 << "ice_pwd_ are not set."; |
354 return; | 384 return; |
355 } | 385 } |
356 | 386 |
357 // Kick off an allocator session | 387 // Kick off an allocator session |
358 Allocate(); | 388 Allocate(); |
359 | 389 |
360 // Start pinging as the ports come in. | 390 // Start pinging as the ports come in. |
361 thread()->Post(this, MSG_PING); | 391 thread()->Post(this, MSG_CHECK_AND_PING); |
362 | |
363 thread()->PostDelayed( | |
364 check_receiving_delay_, this, MSG_CHECK_RECEIVING); | |
365 } | 392 } |
366 | 393 |
367 // A new port is available, attempt to make connections for it | 394 // A new port is available, attempt to make connections for it |
368 void P2PTransportChannel::OnPortReady(PortAllocatorSession *session, | 395 void P2PTransportChannel::OnPortReady(PortAllocatorSession *session, |
369 PortInterface* port) { | 396 PortInterface* port) { |
370 ASSERT(worker_thread_ == rtc::Thread::Current()); | 397 ASSERT(worker_thread_ == rtc::Thread::Current()); |
371 | 398 |
372 // Set in-effect options on the new port | 399 // Set in-effect options on the new port |
373 for (OptionMap::const_iterator it = options_.begin(); | 400 for (OptionMap::const_iterator it = options_.begin(); |
374 it != options_.end(); | 401 it != options_.end(); |
(...skipping 18 matching lines...) Expand all Loading... | |
393 port->SignalDestroyed.connect(this, &P2PTransportChannel::OnPortDestroyed); | 420 port->SignalDestroyed.connect(this, &P2PTransportChannel::OnPortDestroyed); |
394 port->SignalRoleConflict.connect( | 421 port->SignalRoleConflict.connect( |
395 this, &P2PTransportChannel::OnRoleConflict); | 422 this, &P2PTransportChannel::OnRoleConflict); |
396 | 423 |
397 // Attempt to create a connection from this new port to all of the remote | 424 // Attempt to create a connection from this new port to all of the remote |
398 // candidates that we were given so far. | 425 // candidates that we were given so far. |
399 | 426 |
400 std::vector<RemoteCandidate>::iterator iter; | 427 std::vector<RemoteCandidate>::iterator iter; |
401 for (iter = remote_candidates_.begin(); iter != remote_candidates_.end(); | 428 for (iter = remote_candidates_.begin(); iter != remote_candidates_.end(); |
402 ++iter) { | 429 ++iter) { |
403 CreateConnection(port, *iter, iter->origin_port(), false); | 430 CreateConnection(port, *iter, iter->origin_port()); |
404 } | 431 } |
405 | 432 |
406 SortConnections(); | 433 SortConnections(); |
407 } | 434 } |
408 | 435 |
409 // A new candidate is available, let listeners know | 436 // A new candidate is available, let listeners know |
410 void P2PTransportChannel::OnCandidatesReady( | 437 void P2PTransportChannel::OnCandidatesReady( |
411 PortAllocatorSession *session, const std::vector<Candidate>& candidates) { | 438 PortAllocatorSession *session, const std::vector<Candidate>& candidates) { |
412 ASSERT(worker_thread_ == rtc::Thread::Current()); | 439 ASSERT(worker_thread_ == rtc::Thread::Current()); |
413 for (size_t i = 0; i < candidates.size(); ++i) { | 440 for (size_t i = 0; i < candidates.size(); ++i) { |
(...skipping 195 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
609 // remote candidate with an older generation arrives, drop it. | 636 // remote candidate with an older generation arrives, drop it. |
610 if (generation != 0 && generation < remote_candidate_generation_) { | 637 if (generation != 0 && generation < remote_candidate_generation_) { |
611 LOG(LS_WARNING) << "Dropping a remote candidate because its generation " | 638 LOG(LS_WARNING) << "Dropping a remote candidate because its generation " |
612 << generation | 639 << generation |
613 << " is lower than the current remote generation " | 640 << " is lower than the current remote generation " |
614 << remote_candidate_generation_; | 641 << remote_candidate_generation_; |
615 return; | 642 return; |
616 } | 643 } |
617 | 644 |
618 // Create connections to this remote candidate. | 645 // Create connections to this remote candidate. |
619 CreateConnections(candidate, NULL, false); | 646 CreateConnections(candidate, NULL); |
620 | 647 |
621 // Resort the connections list, which may have new elements. | 648 // Resort the connections list, which may have new elements. |
622 SortConnections(); | 649 SortConnections(); |
623 } | 650 } |
624 | 651 |
625 // Creates connections from all of the ports that we care about to the given | 652 // Creates connections from all of the ports that we care about to the given |
626 // remote candidate. The return value is true if we created a connection from | 653 // remote candidate. The return value is true if we created a connection from |
627 // the origin port. | 654 // the origin port. |
628 bool P2PTransportChannel::CreateConnections(const Candidate& remote_candidate, | 655 bool P2PTransportChannel::CreateConnections(const Candidate& remote_candidate, |
629 PortInterface* origin_port, | 656 PortInterface* origin_port) { |
630 bool readable) { | |
631 ASSERT(worker_thread_ == rtc::Thread::Current()); | 657 ASSERT(worker_thread_ == rtc::Thread::Current()); |
632 | 658 |
633 Candidate new_remote_candidate(remote_candidate); | 659 Candidate new_remote_candidate(remote_candidate); |
634 new_remote_candidate.set_generation( | 660 new_remote_candidate.set_generation( |
635 GetRemoteCandidateGeneration(remote_candidate)); | 661 GetRemoteCandidateGeneration(remote_candidate)); |
636 // ICE candidates don't need to have username and password set, but | 662 // ICE candidates don't need to have username and password set, but |
637 // the code below this (specifically, ConnectionRequest::Prepare in | 663 // the code below this (specifically, ConnectionRequest::Prepare in |
638 // port.cc) uses the remote candidates's username. So, we set it | 664 // port.cc) uses the remote candidates's username. So, we set it |
639 // here. | 665 // here. |
640 if (remote_candidate.username().empty()) { | 666 if (remote_candidate.username().empty()) { |
(...skipping 17 matching lines...) Expand all Loading... | |
658 } | 684 } |
659 | 685 |
660 // Add a new connection for this candidate to every port that allows such a | 686 // Add a new connection for this candidate to every port that allows such a |
661 // connection (i.e., if they have compatible protocols) and that does not | 687 // connection (i.e., if they have compatible protocols) and that does not |
662 // already have a connection to an equivalent candidate. We must be careful | 688 // already have a connection to an equivalent candidate. We must be careful |
663 // to make sure that the origin port is included, even if it was pruned, | 689 // to make sure that the origin port is included, even if it was pruned, |
664 // since that may be the only port that can create this connection. | 690 // since that may be the only port that can create this connection. |
665 bool created = false; | 691 bool created = false; |
666 std::vector<PortInterface *>::reverse_iterator it; | 692 std::vector<PortInterface *>::reverse_iterator it; |
667 for (it = ports_.rbegin(); it != ports_.rend(); ++it) { | 693 for (it = ports_.rbegin(); it != ports_.rend(); ++it) { |
668 if (CreateConnection(*it, new_remote_candidate, origin_port, readable)) { | 694 if (CreateConnection(*it, new_remote_candidate, origin_port)) { |
669 if (*it == origin_port) | 695 if (*it == origin_port) |
670 created = true; | 696 created = true; |
671 } | 697 } |
672 } | 698 } |
673 | 699 |
674 if ((origin_port != NULL) && | 700 if ((origin_port != NULL) && |
675 std::find(ports_.begin(), ports_.end(), origin_port) == ports_.end()) { | 701 std::find(ports_.begin(), ports_.end(), origin_port) == ports_.end()) { |
676 if (CreateConnection( | 702 if (CreateConnection(origin_port, new_remote_candidate, origin_port)) |
677 origin_port, new_remote_candidate, origin_port, readable)) | |
678 created = true; | 703 created = true; |
679 } | 704 } |
680 | 705 |
681 // Remember this remote candidate so that we can add it to future ports. | 706 // Remember this remote candidate so that we can add it to future ports. |
682 RememberRemoteCandidate(new_remote_candidate, origin_port); | 707 RememberRemoteCandidate(new_remote_candidate, origin_port); |
683 | 708 |
684 return created; | 709 return created; |
685 } | 710 } |
686 | 711 |
687 // Setup a connection object for the local and remote candidate combination. | 712 // Setup a connection object for the local and remote candidate combination. |
688 // And then listen to connection object for changes. | 713 // And then listen to connection object for changes. |
689 bool P2PTransportChannel::CreateConnection(PortInterface* port, | 714 bool P2PTransportChannel::CreateConnection(PortInterface* port, |
690 const Candidate& remote_candidate, | 715 const Candidate& remote_candidate, |
691 PortInterface* origin_port, | 716 PortInterface* origin_port) { |
692 bool readable) { | |
693 // Look for an existing connection with this remote address. If one is not | 717 // Look for an existing connection with this remote address. If one is not |
694 // found, then we can create a new connection for this address. | 718 // found, then we can create a new connection for this address. |
695 Connection* connection = port->GetConnection(remote_candidate.address()); | 719 Connection* connection = port->GetConnection(remote_candidate.address()); |
696 if (connection != NULL) { | 720 if (connection != NULL) { |
697 connection->MaybeUpdatePeerReflexiveCandidate(remote_candidate); | 721 connection->MaybeUpdatePeerReflexiveCandidate(remote_candidate); |
698 | 722 |
699 // It is not legal to try to change any of the parameters of an existing | 723 // It is not legal to try to change any of the parameters of an existing |
700 // connection; however, the other side can send a duplicate candidate. | 724 // connection; however, the other side can send a duplicate candidate. |
701 if (!remote_candidate.IsEquivalent(connection->remote_candidate())) { | 725 if (!remote_candidate.IsEquivalent(connection->remote_candidate())) { |
702 LOG(INFO) << "Attempt to change a remote candidate." | 726 LOG(INFO) << "Attempt to change a remote candidate." |
(...skipping 14 matching lines...) Expand all Loading... | |
717 connection = port->CreateConnection(remote_candidate, origin); | 741 connection = port->CreateConnection(remote_candidate, origin); |
718 if (!connection) | 742 if (!connection) |
719 return false; | 743 return false; |
720 | 744 |
721 AddConnection(connection); | 745 AddConnection(connection); |
722 | 746 |
723 LOG_J(LS_INFO, this) << "Created connection with origin=" << origin << ", (" | 747 LOG_J(LS_INFO, this) << "Created connection with origin=" << origin << ", (" |
724 << connections_.size() << " total)"; | 748 << connections_.size() << " total)"; |
725 } | 749 } |
726 | 750 |
727 // If we are readable, it is because we are creating this in response to a | |
728 // ping from the other side. This will cause the state to become readable. | |
729 if (readable) | |
730 connection->ReceivedPing(); | |
731 | |
732 return true; | 751 return true; |
733 } | 752 } |
734 | 753 |
735 bool P2PTransportChannel::FindConnection( | 754 bool P2PTransportChannel::FindConnection( |
736 cricket::Connection* connection) const { | 755 cricket::Connection* connection) const { |
737 std::vector<Connection*>::const_iterator citer = | 756 std::vector<Connection*>::const_iterator citer = |
738 std::find(connections_.begin(), connections_.end(), connection); | 757 std::find(connections_.begin(), connections_.end(), connection); |
739 return citer != connections_.end(); | 758 return citer != connections_.end(); |
740 } | 759 } |
741 | 760 |
(...skipping 102 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
844 } | 863 } |
845 | 864 |
846 bool P2PTransportChannel::GetStats(ConnectionInfos *infos) { | 865 bool P2PTransportChannel::GetStats(ConnectionInfos *infos) { |
847 ASSERT(worker_thread_ == rtc::Thread::Current()); | 866 ASSERT(worker_thread_ == rtc::Thread::Current()); |
848 // Gather connection infos. | 867 // Gather connection infos. |
849 infos->clear(); | 868 infos->clear(); |
850 | 869 |
851 std::vector<Connection *>::const_iterator it; | 870 std::vector<Connection *>::const_iterator it; |
852 for (it = connections_.begin(); it != connections_.end(); ++it) { | 871 for (it = connections_.begin(); it != connections_.end(); ++it) { |
853 Connection *connection = *it; | 872 Connection *connection = *it; |
873 if (connection->pruned() && !connection->receiving()) { | |
874 continue; | |
875 } | |
854 ConnectionInfo info; | 876 ConnectionInfo info; |
855 info.best_connection = (best_connection_ == connection); | 877 info.best_connection = (best_connection_ == connection); |
856 info.readable = | 878 info.receiving = connection->receiving(); |
857 (connection->read_state() == Connection::STATE_READABLE); | |
858 info.writable = | 879 info.writable = |
859 (connection->write_state() == Connection::STATE_WRITABLE); | 880 (connection->write_state() == Connection::STATE_WRITABLE); |
860 info.timeout = | 881 info.timeout = |
861 (connection->write_state() == Connection::STATE_WRITE_TIMEOUT); | 882 (connection->write_state() == Connection::STATE_WRITE_TIMEOUT); |
862 info.new_connection = !connection->reported(); | 883 info.new_connection = !connection->reported(); |
863 connection->set_reported(true); | 884 connection->set_reported(true); |
864 info.rtt = connection->rtt(); | 885 info.rtt = connection->rtt(); |
865 info.sent_total_bytes = connection->sent_total_bytes(); | 886 info.sent_total_bytes = connection->sent_total_bytes(); |
866 info.sent_bytes_second = connection->sent_bytes_second(); | 887 info.sent_bytes_second = connection->sent_bytes_second(); |
867 info.sent_discarded_packets = connection->sent_discarded_packets(); | 888 info.sent_discarded_packets = connection->sent_discarded_packets(); |
(...skipping 20 matching lines...) Expand all Loading... | |
888 // Begin allocate (or immediately re-allocate, if MSG_ALLOCATE pending) | 909 // Begin allocate (or immediately re-allocate, if MSG_ALLOCATE pending) |
889 void P2PTransportChannel::Allocate() { | 910 void P2PTransportChannel::Allocate() { |
890 // Time for a new allocator, lets make sure we have a signalling channel | 911 // Time for a new allocator, lets make sure we have a signalling channel |
891 // to communicate candidates through first. | 912 // to communicate candidates through first. |
892 waiting_for_signaling_ = true; | 913 waiting_for_signaling_ = true; |
893 SignalRequestSignaling(this); | 914 SignalRequestSignaling(this); |
894 } | 915 } |
895 | 916 |
896 // Monitor connection states. | 917 // Monitor connection states. |
897 void P2PTransportChannel::UpdateConnectionStates() { | 918 void P2PTransportChannel::UpdateConnectionStates() { |
898 uint32 now = rtc::Time(); | |
899 | |
900 // We need to copy the list of connections since some may delete themselves | 919 // We need to copy the list of connections since some may delete themselves |
901 // when we call UpdateState. | 920 // when we call UpdateState. |
921 uint32 now = rtc::Time(); | |
902 for (uint32 i = 0; i < connections_.size(); ++i) | 922 for (uint32 i = 0; i < connections_.size(); ++i) |
903 connections_[i]->UpdateState(now); | 923 connections_[i]->UpdateState(now); |
904 } | 924 } |
905 | 925 |
906 // Prepare for best candidate sorting. | 926 // Prepare for best candidate sorting. |
907 void P2PTransportChannel::RequestSort() { | 927 void P2PTransportChannel::RequestSort() { |
908 if (!sort_dirty_) { | 928 if (!sort_dirty_) { |
909 worker_thread_->Post(this, MSG_SORT); | 929 worker_thread_->Post(this, MSG_SORT); |
910 sort_dirty_ = true; | 930 sort_dirty_ = true; |
911 } | 931 } |
(...skipping 10 matching lines...) Expand all Loading... | |
922 | 942 |
923 // Any changes after this point will require a re-sort. | 943 // Any changes after this point will require a re-sort. |
924 sort_dirty_ = false; | 944 sort_dirty_ = false; |
925 | 945 |
926 // Find the best alternative connection by sorting. It is important to note | 946 // Find the best alternative connection by sorting. It is important to note |
927 // that amongst equal preference, writable connections, this will choose the | 947 // that amongst equal preference, writable connections, this will choose the |
928 // one whose estimated latency is lowest. So it is the only one that we | 948 // one whose estimated latency is lowest. So it is the only one that we |
929 // need to consider switching to. | 949 // need to consider switching to. |
930 ConnectionCompare cmp; | 950 ConnectionCompare cmp; |
931 std::stable_sort(connections_.begin(), connections_.end(), cmp); | 951 std::stable_sort(connections_.begin(), connections_.end(), cmp); |
932 LOG(LS_VERBOSE) << "Sorting available connections:"; | 952 LOG(LS_VERBOSE) << "Sorting " << connections_.size() |
953 << " available connections:"; | |
933 for (uint32 i = 0; i < connections_.size(); ++i) { | 954 for (uint32 i = 0; i < connections_.size(); ++i) { |
934 LOG(LS_VERBOSE) << connections_[i]->ToString(); | 955 LOG(LS_VERBOSE) << connections_[i]->ToString(); |
935 } | 956 } |
936 | 957 |
937 Connection* top_connection = | 958 Connection* top_connection = |
938 (connections_.size() > 0) ? connections_[0] : nullptr; | 959 (connections_.size() > 0) ? connections_[0] : nullptr; |
939 | 960 |
940 // If necessary, switch to the new choice. | 961 // If necessary, switch to the new choice. |
941 // Note that |top_connection| doesn't have to be writable to become the best | 962 // Note that |top_connection| doesn't have to be writable to become the best |
942 // connection although it will have higher priority if it is writable. | 963 // connection although it will have higher priority if it is writable. |
943 // The controlled side can switch the best connection only if the current | 964 if (ShouldSwitch(best_connection_, top_connection, ice_role_)) { |
944 // |best connection_| has not been nominated by the controlling side yet. | |
945 if ((ice_role_ == ICEROLE_CONTROLLING || !best_nominated_connection()) && | |
946 ShouldSwitch(best_connection_, top_connection)) { | |
947 LOG(LS_INFO) << "Switching best connection: " << top_connection->ToString(); | 965 LOG(LS_INFO) << "Switching best connection: " << top_connection->ToString(); |
948 SwitchBestConnectionTo(top_connection); | 966 SwitchBestConnectionTo(top_connection); |
949 } | 967 } |
950 | 968 |
951 // Controlled side can prune only if the best connection has been nominated. | 969 // Controlled side can prune only if the best connection has been nominated. |
952 // because otherwise it may delete the connection that will be selected by | 970 // because otherwise it may delete the connection that will be selected by |
953 // the controlling side. | 971 // the controlling side. |
954 if (ice_role_ == ICEROLE_CONTROLLING || best_nominated_connection()) { | 972 if (ice_role_ == ICEROLE_CONTROLLING || best_nominated_connection()) { |
955 PruneConnections(); | 973 PruneConnections(); |
956 } | 974 } |
(...skipping 27 matching lines...) Expand all Loading... | |
984 : nullptr; | 1002 : nullptr; |
985 } | 1003 } |
986 | 1004 |
987 void P2PTransportChannel::PruneConnections() { | 1005 void P2PTransportChannel::PruneConnections() { |
988 // We can prune any connection for which there is a connected, writable | 1006 // We can prune any connection for which there is a connected, writable |
989 // connection on the same network with better or equal priority. We leave | 1007 // connection on the same network with better or equal priority. We leave |
990 // those with better priority just in case they become writable later (at | 1008 // those with better priority just in case they become writable later (at |
991 // which point, we would prune out the current best connection). We leave | 1009 // which point, we would prune out the current best connection). We leave |
992 // connections on other networks because they may not be using the same | 1010 // connections on other networks because they may not be using the same |
993 // resources and they may represent very distinct paths over which we can | 1011 // resources and they may represent very distinct paths over which we can |
994 // switch. If the |primier| connection is not connected, we may be | 1012 // switch. If the |premier| connection is not connected, we may be |
995 // reconnecting a TCP connection and temporarily do not prune connections in | 1013 // reconnecting a TCP connection and temporarily do not prune connections in |
996 // this network. See the big comment in CompareConnections. | 1014 // this network. See the big comment in CompareConnections. |
997 | 1015 |
998 // Get a list of the networks that we are using. | 1016 // Get a list of the networks that we are using. |
999 std::set<rtc::Network*> networks; | 1017 std::set<rtc::Network*> networks; |
1000 for (const Connection* conn : connections_) { | 1018 for (const Connection* conn : connections_) { |
1001 networks.insert(conn->port()->Network()); | 1019 networks.insert(conn->port()->Network()); |
1002 } | 1020 } |
1003 for (rtc::Network* network : networks) { | 1021 for (rtc::Network* network : networks) { |
1004 Connection* primier = GetBestConnectionOnNetwork(network); | 1022 Connection* premier = GetBestConnectionOnNetwork(network); |
1005 if (!(primier && primier->writable() && primier->connected())) { | 1023 if (!(premier && premier->writable() && premier->connected())) { |
1006 continue; | 1024 continue; |
1007 } | 1025 } |
1008 | 1026 premier->Prune(false); // Un-prune the premier connection. |
1009 for (Connection* conn : connections_) { | 1027 for (Connection* conn : connections_) { |
1010 if ((conn != primier) && (conn->port()->Network() == network) && | 1028 if ((conn != premier) && (conn->port()->Network() == network) && |
1011 (CompareConnectionCandidates(primier, conn) >= 0)) { | 1029 (CompareConnectionCandidates(premier, conn) >= 0)) { |
1012 conn->Prune(); | 1030 conn->Prune(true); |
pthatcher1
2015/09/17 22:01:17
What does "true" here mean?
honghaiz3
2015/09/21 22:53:41
true means prune it.
false means un-prune it.
I t
honghaiz3
2015/09/21 23:17:15
I re-named these to Prune and UnPrune for better r
| |
1013 } | 1031 } |
1014 } | 1032 } |
1015 } | 1033 } |
1016 } | 1034 } |
1017 | 1035 |
1018 // Track the best connection, and let listeners know | 1036 // Track the best connection, and let listeners know |
1019 void P2PTransportChannel::SwitchBestConnectionTo(Connection* conn) { | 1037 void P2PTransportChannel::SwitchBestConnectionTo(Connection* conn) { |
1020 // Note: if conn is NULL, the previous best_connection_ has been destroyed, | 1038 // Note: if conn is NULL, the previous best_connection_ has been destroyed, |
1021 // so don't use it. | 1039 // so don't use it. |
1022 Connection* old_best_connection = best_connection_; | 1040 Connection* old_best_connection = best_connection_; |
1023 best_connection_ = conn; | 1041 best_connection_ = conn; |
1024 if (best_connection_) { | 1042 if (best_connection_) { |
1025 if (old_best_connection) { | 1043 if (old_best_connection) { |
1026 LOG_J(LS_INFO, this) << "Previous best connection: " | 1044 LOG_J(LS_INFO, this) << "Previous best connection: " |
1027 << old_best_connection->ToString(); | 1045 << old_best_connection->ToString(); |
1028 } | 1046 } |
1029 LOG_J(LS_INFO, this) << "New best connection: " | 1047 LOG_J(LS_INFO, this) << "New best connection: " |
1030 << best_connection_->ToString(); | 1048 << best_connection_->ToString(); |
1031 SignalRouteChange(this, best_connection_->remote_candidate()); | 1049 SignalRouteChange(this, best_connection_->remote_candidate()); |
1032 // When it just switched to a best connection, set receiving to true. | |
1033 set_receiving(true); | |
1034 } else { | 1050 } else { |
1035 LOG_J(LS_INFO, this) << "No best connection"; | 1051 LOG_J(LS_INFO, this) << "No best connection"; |
1036 } | 1052 } |
1037 } | 1053 } |
1038 | 1054 |
1039 void P2PTransportChannel::UpdateChannelState() { | 1055 void P2PTransportChannel::UpdateChannelState() { |
1040 // The Handle* functions already set the writable state. We'll just double- | 1056 // The Handle* functions already set the writable state. We'll just double- |
1041 // check it here. | 1057 // check it here. |
1042 bool writable = ((best_connection_ != NULL) && | 1058 bool writable = best_connection_ && best_connection_->writable(); |
1043 (best_connection_->write_state() == | |
1044 Connection::STATE_WRITABLE)); | |
1045 ASSERT(writable == this->writable()); | 1059 ASSERT(writable == this->writable()); |
1046 if (writable != this->writable()) | 1060 if (writable != this->writable()) |
1047 LOG(LS_ERROR) << "UpdateChannelState: writable state mismatch"; | 1061 LOG(LS_ERROR) << "UpdateChannelState: writable state mismatch"; |
1048 | 1062 |
1049 bool readable = false; | 1063 bool receiving = false; |
1050 for (uint32 i = 0; i < connections_.size(); ++i) { | 1064 for (const Connection* connection : connections_) { |
1051 if (connections_[i]->read_state() == Connection::STATE_READABLE) { | 1065 if (connection->receiving()) { |
1052 readable = true; | 1066 receiving = true; |
1053 break; | 1067 break; |
1054 } | 1068 } |
1055 } | 1069 } |
pthatcher1
2015/09/17 22:01:17
Can you use std::any_of? That might make this eas
honghaiz3
2015/09/21 22:53:42
Done.
| |
1056 set_readable(readable); | 1070 set_receiving(receiving); |
1057 } | 1071 } |
1058 | 1072 |
1059 // We checked the status of our connections and we had at least one that | 1073 // We checked the status of our connections and we had at least one that |
1060 // was writable, go into the writable state. | 1074 // was writable, go into the writable state. |
1061 void P2PTransportChannel::HandleWritable() { | 1075 void P2PTransportChannel::HandleWritable() { |
1062 ASSERT(worker_thread_ == rtc::Thread::Current()); | 1076 ASSERT(worker_thread_ == rtc::Thread::Current()); |
1063 if (!writable()) { | 1077 if (!writable()) { |
1064 for (uint32 i = 0; i < allocator_sessions_.size(); ++i) { | 1078 for (uint32 i = 0; i < allocator_sessions_.size(); ++i) { |
1065 if (allocator_sessions_[i]->IsGettingPorts()) { | 1079 if (allocator_sessions_[i]->IsGettingPorts()) { |
1066 allocator_sessions_[i]->StopGettingPorts(); | 1080 allocator_sessions_[i]->StopGettingPorts(); |
(...skipping 12 matching lines...) Expand all Loading... | |
1079 was_writable_ = false; | 1093 was_writable_ = false; |
1080 set_writable(false); | 1094 set_writable(false); |
1081 } | 1095 } |
1082 } | 1096 } |
1083 | 1097 |
1084 void P2PTransportChannel::HandleAllTimedOut() { | 1098 void P2PTransportChannel::HandleAllTimedOut() { |
1085 // Currently we are treating this as channel not writable. | 1099 // Currently we are treating this as channel not writable. |
1086 HandleNotWritable(); | 1100 HandleNotWritable(); |
1087 } | 1101 } |
1088 | 1102 |
1103 bool P2PTransportChannel::weak() const { | |
1104 return !(best_connection_ && best_connection_->receiving() && writable()); | |
1105 } | |
1106 | |
1089 // If we have a best connection, return it, otherwise return top one in the | 1107 // If we have a best connection, return it, otherwise return top one in the |
1090 // list (later we will mark it best). | 1108 // list (later we will mark it best). |
1091 Connection* P2PTransportChannel::GetBestConnectionOnNetwork( | 1109 Connection* P2PTransportChannel::GetBestConnectionOnNetwork( |
1092 rtc::Network* network) const { | 1110 rtc::Network* network) const { |
1093 // If the best connection is on this network, then it wins. | 1111 // If the best connection is on this network, then it wins. |
1094 if (best_connection_ && (best_connection_->port()->Network() == network)) | 1112 if (best_connection_ && (best_connection_->port()->Network() == network)) |
1095 return best_connection_; | 1113 return best_connection_; |
1096 | 1114 |
1097 // Otherwise, we return the top-most in sorted order. | 1115 // Otherwise, we return the top-most in sorted order. |
1098 for (uint32 i = 0; i < connections_.size(); ++i) { | 1116 for (uint32 i = 0; i < connections_.size(); ++i) { |
1099 if (connections_[i]->port()->Network() == network) | 1117 if (connections_[i]->port()->Network() == network) |
1100 return connections_[i]; | 1118 return connections_[i]; |
1101 } | 1119 } |
1102 | 1120 |
1103 return NULL; | 1121 return NULL; |
1104 } | 1122 } |
1105 | 1123 |
1106 // Handle any queued up requests | 1124 // Handle any queued up requests |
1107 void P2PTransportChannel::OnMessage(rtc::Message *pmsg) { | 1125 void P2PTransportChannel::OnMessage(rtc::Message *pmsg) { |
1108 switch (pmsg->message_id) { | 1126 switch (pmsg->message_id) { |
1109 case MSG_SORT: | 1127 case MSG_SORT: |
1110 OnSort(); | 1128 OnSort(); |
1111 break; | 1129 break; |
1112 case MSG_PING: | 1130 case MSG_CHECK_AND_PING: |
1113 OnPing(); | 1131 OnCheckAndPing(); |
1114 break; | |
1115 case MSG_CHECK_RECEIVING: | |
1116 OnCheckReceiving(); | |
1117 break; | 1132 break; |
1118 default: | 1133 default: |
1119 ASSERT(false); | 1134 ASSERT(false); |
1120 break; | 1135 break; |
1121 } | 1136 } |
1122 } | 1137 } |
1123 | 1138 |
1124 // Handle queued up sort request | 1139 // Handle queued up sort request |
1125 void P2PTransportChannel::OnSort() { | 1140 void P2PTransportChannel::OnSort() { |
1126 // Resort the connections based on the new statistics. | 1141 // Resort the connections based on the new statistics. |
1127 SortConnections(); | 1142 SortConnections(); |
1128 } | 1143 } |
1129 | 1144 |
1130 // Handle queued up ping request | 1145 void P2PTransportChannel::OnCheckAndPing() { |
1131 void P2PTransportChannel::OnPing() { | |
1132 // Make sure the states of the connections are up-to-date (since this affects | |
1133 // which ones are pingable). | |
1134 UpdateConnectionStates(); | 1146 UpdateConnectionStates(); |
1135 | 1147 // When the best connection is neither receiving nor writable, switch to |
1136 // Find the oldest pingable connection and have it do a ping. | 1148 // weak ping delay. |
1137 Connection* conn = FindNextPingableConnection(); | 1149 ping_delay_ = weak() ? WEAK_PING_DELAY : STRONG_PING_DELAY; |
1138 if (conn) | 1150 uint32 now = rtc::Time(); |
1139 PingConnection(conn); | 1151 if ((now >= last_ping_sent_ + ping_delay_) || next_connection_to_ping_) { |
1140 | 1152 Connection* conn = FindNextPingableConnection(); |
1141 // Post ourselves a message to perform the next ping. | 1153 if (conn) { |
1142 uint32 delay = writable() ? WRITABLE_DELAY : UNWRITABLE_DELAY; | 1154 PingConnection(conn); |
1143 thread()->PostDelayed(delay, this, MSG_PING); | 1155 } |
1144 } | |
1145 | |
1146 void P2PTransportChannel::OnCheckReceiving() { | |
1147 // Check receiving only if the best connection has received data packets | |
1148 // because we want to detect not receiving any packets only after the media | |
1149 // have started flowing. | |
1150 if (best_connection_ && best_connection_->recv_total_bytes() > 0) { | |
1151 bool receiving = rtc::Time() <= | |
1152 best_connection_->last_received() + receiving_timeout_; | |
1153 set_receiving(receiving); | |
1154 } | 1156 } |
1155 | 1157 uint32 check_delay = std::min(ping_delay_, check_receiving_delay_); |
1156 thread()->PostDelayed(check_receiving_delay_, this, MSG_CHECK_RECEIVING); | 1158 thread()->PostDelayed(check_delay, this, MSG_CHECK_AND_PING); |
1157 } | 1159 } |
1158 | 1160 |
1159 // Is the connection in a state for us to even consider pinging the other side? | 1161 // Is the connection in a state for us to even consider pinging the other side? |
1160 // We consider a connection pingable even if it's not connected because that's | 1162 // We consider a connection pingable even if it's not connected because that's |
1161 // how a TCP connection is kicked into reconnecting on the active side. | 1163 // how a TCP connection is kicked into reconnecting on the active side. |
1162 bool P2PTransportChannel::IsPingable(Connection* conn) { | 1164 bool P2PTransportChannel::IsPingable(Connection* conn) { |
1163 const Candidate& remote = conn->remote_candidate(); | 1165 const Candidate& remote = conn->remote_candidate(); |
1164 // We should never get this far with an empty remote ufrag. | 1166 // We should never get this far with an empty remote ufrag. |
1165 ASSERT(!remote.username().empty()); | 1167 ASSERT(!remote.username().empty()); |
1166 if (remote.username().empty() || remote.password().empty()) { | 1168 if (remote.username().empty() || remote.password().empty()) { |
1167 // If we don't have an ICE ufrag and pwd, there's no way we can ping. | 1169 // If we don't have an ICE ufrag and pwd, there's no way we can ping. |
1168 return false; | 1170 return false; |
1169 } | 1171 } |
1170 | 1172 |
1171 // An never connected connection cannot be written to at all, so pinging is | 1173 // An never connected connection cannot be written to at all, so pinging is |
1172 // out of the question. However, if it has become WRITABLE, it is in the | 1174 // out of the question. However, if it has become WRITABLE, it is in the |
1173 // reconnecting state so ping is needed. | 1175 // reconnecting state so ping is needed. |
1174 if (!conn->connected() && conn->write_state() != Connection::STATE_WRITABLE) { | 1176 if (!conn->connected() && !conn->writable()) { |
1175 return false; | 1177 return false; |
1176 } | 1178 } |
1177 | 1179 |
1178 if (writable()) { | 1180 // If the channel is weak, ping all candidates. Otherwise, ping only |
1179 // If we are writable, then we only want to ping connections that could be | 1181 // un-pruned candidates. |
1180 // better than this one, i.e., the ones that were not pruned. | 1182 return weak() || !conn->pruned(); |
1181 return (conn->write_state() != Connection::STATE_WRITE_TIMEOUT); | |
1182 } else { | |
1183 // If we are not writable, then we need to try everything that might work. | |
1184 // This includes both connections that do not have write timeout as well as | |
1185 // ones that do not have read timeout. A connection could be readable but | |
1186 // be in write-timeout if we pruned it before. Since the other side is | |
1187 // still pinging it, it very well might still work. | |
1188 return (conn->write_state() != Connection::STATE_WRITE_TIMEOUT) || | |
1189 (conn->read_state() != Connection::STATE_READ_TIMEOUT); | |
1190 } | |
1191 } | 1183 } |
1192 | 1184 |
1193 // Returns the next pingable connection to ping. This will be the oldest | 1185 // Returns the next pingable connection to ping. This will be the oldest |
1194 // pingable connection unless we have a connected, writable connection that is | 1186 // pingable connection unless we have a connected, writable connection that is |
1195 // past the maximum acceptable ping delay. When reconnecting a TCP connection, | 1187 // past the maximum acceptable ping delay. When reconnecting a TCP connection, |
1196 // the best connection is disconnected, although still WRITABLE while | 1188 // the best connection is disconnected, although still WRITABLE while |
1197 // reconnecting. The newly created connection should be selected as the ping | 1189 // reconnecting. The newly created connection should be selected as the ping |
1198 // target to become writable instead. See the big comment in CompareConnections. | 1190 // target to become writable instead. See the big comment in CompareConnections. |
1199 Connection* P2PTransportChannel::FindNextPingableConnection() { | 1191 Connection* P2PTransportChannel::FindNextPingableConnection() { |
1192 if (next_connection_to_ping_ && !next_connection_to_ping_->writable()) { | |
1193 Connection* conn = next_connection_to_ping_; | |
1194 next_connection_to_ping_ = nullptr; | |
1195 return conn; | |
1196 } | |
1200 uint32 now = rtc::Time(); | 1197 uint32 now = rtc::Time(); |
1201 if (best_connection_ && best_connection_->connected() && | 1198 if (best_connection_ && best_connection_->connected() && |
1202 (best_connection_->write_state() == Connection::STATE_WRITABLE) && | 1199 best_connection_->writable() && |
1203 (best_connection_->last_ping_sent() + MAX_CURRENT_WRITABLE_DELAY <= | 1200 (best_connection_->last_ping_sent() + MAX_CURRENT_WRITABLE_DELAY <= |
1204 now)) { | 1201 now)) { |
1205 return best_connection_; | 1202 return best_connection_; |
1206 } | 1203 } |
1207 | 1204 |
1208 // First, find "triggered checks". We ping first those connections | 1205 // First, find "triggered checks". We ping first those connections |
1209 // that have received a ping but have not sent a ping since receiving | 1206 // that have received a ping but have not sent a ping since receiving |
1210 // it (last_received_ping > last_sent_ping). But we shouldn't do | 1207 // it (last_received_ping > last_sent_ping). But we shouldn't do |
1211 // triggered checks if the connection is already writable. | 1208 // triggered checks if the connection is already writable. |
1212 Connection* oldest_needing_triggered_check = nullptr; | 1209 Connection* oldest_needing_triggered_check = nullptr; |
1213 Connection* oldest = nullptr; | 1210 Connection* oldest = nullptr; |
1214 for (Connection* conn : connections_) { | 1211 for (Connection* conn : connections_) { |
1215 if (!IsPingable(conn)) { | 1212 if (!IsPingable(conn)) { |
1216 continue; | 1213 continue; |
1217 } | 1214 } |
1215 | |
1218 bool needs_triggered_check = | 1216 bool needs_triggered_check = |
1219 (!conn->writable() && | 1217 (!conn->writable() && |
1220 conn->last_ping_received() > conn->last_ping_sent()); | 1218 conn->last_ping_received() > conn->last_ping_sent()); |
1221 if (needs_triggered_check && | 1219 if (needs_triggered_check && |
1222 (!oldest_needing_triggered_check || | 1220 (!oldest_needing_triggered_check || |
1223 (conn->last_ping_received() < | 1221 (conn->last_ping_received() < |
1224 oldest_needing_triggered_check->last_ping_received()))) { | 1222 oldest_needing_triggered_check->last_ping_received()))) { |
1225 oldest_needing_triggered_check = conn; | 1223 oldest_needing_triggered_check = conn; |
1226 } | 1224 } |
1227 if (!oldest || (conn->last_ping_sent() < oldest->last_ping_sent())) { | 1225 if (!oldest || (conn->last_ping_sent() < oldest->last_ping_sent())) { |
(...skipping 25 matching lines...) Expand all Loading... | |
1253 bool use_candidate = false; | 1251 bool use_candidate = false; |
1254 if (remote_ice_mode_ == ICEMODE_FULL && ice_role_ == ICEROLE_CONTROLLING) { | 1252 if (remote_ice_mode_ == ICEMODE_FULL && ice_role_ == ICEROLE_CONTROLLING) { |
1255 use_candidate = (conn == best_connection_) || | 1253 use_candidate = (conn == best_connection_) || |
1256 (best_connection_ == NULL) || | 1254 (best_connection_ == NULL) || |
1257 (!best_connection_->writable()) || | 1255 (!best_connection_->writable()) || |
1258 (conn->priority() > best_connection_->priority()); | 1256 (conn->priority() > best_connection_->priority()); |
1259 } else if (remote_ice_mode_ == ICEMODE_LITE && conn == best_connection_) { | 1257 } else if (remote_ice_mode_ == ICEMODE_LITE && conn == best_connection_) { |
1260 use_candidate = best_connection_->writable(); | 1258 use_candidate = best_connection_->writable(); |
1261 } | 1259 } |
1262 conn->set_use_candidate_attr(use_candidate); | 1260 conn->set_use_candidate_attr(use_candidate); |
1263 conn->Ping(rtc::Time()); | 1261 last_ping_sent_ = rtc::Time(); |
1262 conn->Ping(last_ping_sent_); | |
1264 } | 1263 } |
1265 | 1264 |
1266 // When a connection's state changes, we need to figure out who to use as | 1265 // When a connection's state changes, we need to figure out who to use as |
1267 // the best connection again. It could have become usable, or become unusable. | 1266 // the best connection again. It could have become usable, or become unusable. |
1268 void P2PTransportChannel::OnConnectionStateChange(Connection* connection) { | 1267 void P2PTransportChannel::OnConnectionStateChange(Connection* connection) { |
1269 ASSERT(worker_thread_ == rtc::Thread::Current()); | 1268 ASSERT(worker_thread_ == rtc::Thread::Current()); |
1270 | 1269 |
1271 // Update the best connection if the state change is from pending best | 1270 // Update the best connection if the state change is from pending best |
1272 // connection and role is controlled. | 1271 // connection and role is controlled. |
1273 if (ice_role_ == ICEROLE_CONTROLLED) { | 1272 if (ice_role_ == ICEROLE_CONTROLLED) { |
(...skipping 68 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1342 | 1341 |
1343 // Do not deliver, if packet doesn't belong to the correct transport channel. | 1342 // Do not deliver, if packet doesn't belong to the correct transport channel. |
1344 if (!FindConnection(connection)) | 1343 if (!FindConnection(connection)) |
1345 return; | 1344 return; |
1346 | 1345 |
1347 // Let the client know of an incoming packet | 1346 // Let the client know of an incoming packet |
1348 SignalReadPacket(this, data, len, packet_time, 0); | 1347 SignalReadPacket(this, data, len, packet_time, 0); |
1349 | 1348 |
1350 // May need to switch the sending connection based on the receiving media path | 1349 // May need to switch the sending connection based on the receiving media path |
1351 // if this is the controlled side. | 1350 // if this is the controlled side. |
1352 if (ice_role_ == ICEROLE_CONTROLLED && !best_nominated_connection() && | 1351 if (best_connection_ != connection && ice_role_ == ICEROLE_CONTROLLED && |
1353 connection->writable() && best_connection_ != connection) { | 1352 (!best_nominated_connection() || connection->nominated()) && |
1353 connection->writable()) { | |
1354 SwitchBestConnectionTo(connection); | 1354 SwitchBestConnectionTo(connection); |
1355 } | 1355 } |
1356 } | 1356 } |
1357 | 1357 |
1358 void P2PTransportChannel::OnReadyToSend(Connection* connection) { | 1358 void P2PTransportChannel::OnReadyToSend(Connection* connection) { |
1359 if (connection == best_connection_ && writable()) { | 1359 if (connection == best_connection_ && writable()) { |
1360 SignalReadyToSend(this); | 1360 SignalReadyToSend(this); |
1361 } | 1361 } |
1362 } | 1362 } |
1363 | 1363 |
1364 } // namespace cricket | 1364 } // namespace cricket |
OLD | NEW |