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

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

Issue 1311433009: A few updates on connection states (Closed) Base URL: https://chromium.googlesource.com/external/webrtc@master
Patch Set: Created 5 years, 3 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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698