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

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: Merge and address comments 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 not 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;
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 writing, receiving, 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 17 matching lines...) Expand all
141 // TODO: Yes we should definitely do this. The TCP protocol gains 154 // TODO: Yes we should definitely do this. The TCP protocol gains
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 // connection states, static preferences, and then (if those are equal) on
152 bool ShouldSwitch(cricket::Connection* a_conn, cricket::Connection* b_conn) { 165 // latency estimates.
166 bool ShouldSwitch(cricket::Connection* a_conn,
167 cricket::Connection* b_conn,
168 cricket::IceRole ice_role) {
153 if (a_conn == b_conn) 169 if (a_conn == b_conn)
154 return false; 170 return false;
155 171
156 if (!a_conn || !b_conn) // don't think the latter should happen 172 if (!a_conn || !b_conn) // don't think the latter should happen
157 return true; 173 return true;
158 174
159 int prefs_cmp = CompareConnections(a_conn, b_conn); 175 // If the RECEIVING/WRITE/CONNECT states are different, we should switch
160 if (prefs_cmp < 0) 176 // regardless of the nominated state. Otherwise, do not switch if |a_conn| is
161 return true; 177 // nominated.
162 if (prefs_cmp > 0) 178 int state_cmp = CompareConnectionStates(a_conn, b_conn);
179 if (state_cmp != 0) {
180 return state_cmp < 0;
181 }
182 if (ice_role == cricket::ICEROLE_CONTROLLED && a_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 sort_dirty_(false),
186 was_writable_(false), 213 was_writable_(false),
187 remote_ice_mode_(ICEMODE_FULL), 214 remote_ice_mode_(ICEMODE_FULL),
188 ice_role_(ICEROLE_UNKNOWN), 215 ice_role_(ICEROLE_UNKNOWN),
189 tiebreaker_(0), 216 tiebreaker_(0),
190 remote_candidate_generation_(0), 217 remote_candidate_generation_(0),
191 check_receiving_delay_(MIN_CHECK_RECEIVING_DELAY * 5), 218 check_receiving_delay_(MIN_CHECK_RECEIVING_DELAY * 5),
192 receiving_timeout_(MIN_CHECK_RECEIVING_DELAY * 50) { 219 receiving_timeout_(MIN_CHECK_RECEIVING_DELAY * 50),
193 } 220 last_ping_sent_(0) {}
194 221
195 P2PTransportChannel::~P2PTransportChannel() { 222 P2PTransportChannel::~P2PTransportChannel() {
196 ASSERT(worker_thread_ == rtc::Thread::Current()); 223 ASSERT(worker_thread_ == rtc::Thread::Current());
197 224
198 for (uint32 i = 0; i < allocator_sessions_.size(); ++i) 225 for (uint32 i = 0; i < allocator_sessions_.size(); ++i)
199 delete allocator_sessions_[i]; 226 delete allocator_sessions_[i];
200 } 227 }
201 228
202 // Add the allocator session to our list so that we know which sessions 229 // Add the allocator session to our list so that we know which sessions
203 // are still active. 230 // are still active.
(...skipping 45 matching lines...) Expand 10 before | Expand all | Expand 10 after
249 if (!ports_.empty()) { 276 if (!ports_.empty()) {
250 LOG(LS_ERROR) 277 LOG(LS_ERROR)
251 << "Attempt to change tiebreaker after Port has been allocated."; 278 << "Attempt to change tiebreaker after Port has been allocated.";
252 return; 279 return;
253 } 280 }
254 281
255 tiebreaker_ = tiebreaker; 282 tiebreaker_ = tiebreaker;
256 } 283 }
257 284
258 // Currently a channel is considered ICE completed once there is no 285 // Currently a channel is considered ICE completed once there is no
259 // more than one connection per Network. This works for a single NIC 286 // more than one connection per Network that is not pruned.
260 // with both IPv4 and IPv6 enabled. However, this condition won't 287 // If all connections are pruned, declare transport failure.
261 // happen when there are multiple NICs and all of them have
262 // connectivity.
263 // TODO(guoweis): Change Completion to be driven by a channel level
264 // timer.
265 TransportChannelState P2PTransportChannel::GetState() const { 288 TransportChannelState P2PTransportChannel::GetState() const {
266 std::set<rtc::Network*> networks; 289 std::set<rtc::Network*> networks_with_unpruned_connections;
267 290 for (const Connection* connection : connections_) {
268 if (connections_.size() == 0) { 291 if (connection->pruned()) {
269 return TransportChannelState::STATE_FAILED; 292 continue;
270 } 293 }
271 294 rtc::Network* network = connection->port()->Network();
272 for (uint32 i = 0; i < connections_.size(); ++i) { 295 if (networks_with_unpruned_connections.find(network) ==
273 rtc::Network* network = connections_[i]->port()->Network(); 296 networks_with_unpruned_connections.end()) {
274 if (networks.find(network) == networks.end()) { 297 networks_with_unpruned_connections.insert(network);
275 networks.insert(network);
276 } else { 298 } else {
277 LOG_J(LS_VERBOSE, this) << "Ice not completed yet for this channel as " 299 LOG_J(LS_VERBOSE, this) << "Ice not completed yet for this channel as "
278 << network->ToString() 300 << network->ToString()
279 << " has more than 1 connection."; 301 << " has more than 1 connection.";
280 return TransportChannelState::STATE_CONNECTING; 302 return TransportChannelState::STATE_CONNECTING;
281 } 303 }
282 } 304 }
305 if (networks_with_unpruned_connections.size() == 0) {
306 return TransportChannelState::STATE_FAILED;
307 }
308
283 LOG_J(LS_VERBOSE, this) << "Ice is completed for this channel."; 309 LOG_J(LS_VERBOSE, this) << "Ice is completed for this channel.";
284
285 return TransportChannelState::STATE_COMPLETED; 310 return TransportChannelState::STATE_COMPLETED;
286 } 311 }
287 312
288 void P2PTransportChannel::SetIceCredentials(const std::string& ice_ufrag, 313 void P2PTransportChannel::SetIceCredentials(const std::string& ice_ufrag,
289 const std::string& ice_pwd) { 314 const std::string& ice_pwd) {
290 ASSERT(worker_thread_ == rtc::Thread::Current()); 315 ASSERT(worker_thread_ == rtc::Thread::Current());
291 bool ice_restart = false; 316 bool ice_restart = false;
292 if (!ice_ufrag_.empty() && !ice_pwd_.empty()) { 317 if (!ice_ufrag_.empty() && !ice_pwd_.empty()) {
293 // Restart candidate allocation if there is any change in either 318 // Restart candidate allocation if there is any change in either
294 // ice ufrag or password. 319 // ice ufrag or password.
(...skipping 45 matching lines...) Expand 10 before | Expand all | Expand 10 after
340 } 365 }
341 receiving_timeout_ = receiving_timeout_ms; 366 receiving_timeout_ = receiving_timeout_ms;
342 check_receiving_delay_ = 367 check_receiving_delay_ =
343 std::max(MIN_CHECK_RECEIVING_DELAY, receiving_timeout_ / 10); 368 std::max(MIN_CHECK_RECEIVING_DELAY, receiving_timeout_ / 10);
344 369
345 for (Connection* connection : connections_) { 370 for (Connection* connection : connections_) {
346 connection->set_receiving_timeout(receiving_timeout_); 371 connection->set_receiving_timeout(receiving_timeout_);
347 } 372 }
348 LOG(LS_VERBOSE) << "Set ICE receiving timeout to " << receiving_timeout_ 373 LOG(LS_VERBOSE) << "Set ICE receiving timeout to " << receiving_timeout_
349 << " milliseconds"; 374 << " milliseconds";
375 for (Connection* connection : connections_) {
376 connection->set_receiving_timeout(receiving_timeout_);
377 }
350 } 378 }
351 379
352 // Go into the state of processing candidates, and running in general 380 // Go into the state of processing candidates, and running in general
353 void P2PTransportChannel::Connect() { 381 void P2PTransportChannel::Connect() {
354 ASSERT(worker_thread_ == rtc::Thread::Current()); 382 ASSERT(worker_thread_ == rtc::Thread::Current());
355 if (ice_ufrag_.empty() || ice_pwd_.empty()) { 383 if (ice_ufrag_.empty() || ice_pwd_.empty()) {
356 ASSERT(false); 384 ASSERT(false);
357 LOG(LS_ERROR) << "P2PTransportChannel::Connect: The ice_ufrag_ and the " 385 LOG(LS_ERROR) << "P2PTransportChannel::Connect: The ice_ufrag_ and the "
358 << "ice_pwd_ are not set."; 386 << "ice_pwd_ are not set.";
359 return; 387 return;
360 } 388 }
361 389
362 // Kick off an allocator session 390 // Kick off an allocator session
363 Allocate(); 391 Allocate();
364 392
365 // Start pinging as the ports come in. 393 // Start pinging as the ports come in.
366 thread()->Post(this, MSG_PING); 394 thread()->Post(this, MSG_CHECK_AND_PING);
367
368 thread()->PostDelayed(
369 check_receiving_delay_, this, MSG_CHECK_RECEIVING);
370 } 395 }
371 396
372 // A new port is available, attempt to make connections for it 397 // A new port is available, attempt to make connections for it
373 void P2PTransportChannel::OnPortReady(PortAllocatorSession *session, 398 void P2PTransportChannel::OnPortReady(PortAllocatorSession *session,
374 PortInterface* port) { 399 PortInterface* port) {
375 ASSERT(worker_thread_ == rtc::Thread::Current()); 400 ASSERT(worker_thread_ == rtc::Thread::Current());
376 401
377 // Set in-effect options on the new port 402 // Set in-effect options on the new port
378 for (OptionMap::const_iterator it = options_.begin(); 403 for (OptionMap::const_iterator it = options_.begin();
379 it != options_.end(); 404 it != options_.end();
(...skipping 461 matching lines...) Expand 10 before | Expand all | Expand 10 after
841 } 866 }
842 867
843 bool P2PTransportChannel::GetStats(ConnectionInfos *infos) { 868 bool P2PTransportChannel::GetStats(ConnectionInfos *infos) {
844 ASSERT(worker_thread_ == rtc::Thread::Current()); 869 ASSERT(worker_thread_ == rtc::Thread::Current());
845 // Gather connection infos. 870 // Gather connection infos.
846 infos->clear(); 871 infos->clear();
847 872
848 std::vector<Connection *>::const_iterator it; 873 std::vector<Connection *>::const_iterator it;
849 for (it = connections_.begin(); it != connections_.end(); ++it) { 874 for (it = connections_.begin(); it != connections_.end(); ++it) {
850 Connection *connection = *it; 875 Connection *connection = *it;
876 if (connection->pruned() && !connection->receiving()) {
877 continue;
878 }
851 ConnectionInfo info; 879 ConnectionInfo info;
852 info.best_connection = (best_connection_ == connection); 880 info.best_connection = (best_connection_ == connection);
853 info.receiving = connection->receiving(); 881 info.receiving = connection->receiving();
854 info.writable = 882 info.writable =
855 (connection->write_state() == Connection::STATE_WRITABLE); 883 (connection->write_state() == Connection::STATE_WRITABLE);
856 info.timeout = 884 info.timeout =
857 (connection->write_state() == Connection::STATE_WRITE_TIMEOUT); 885 (connection->write_state() == Connection::STATE_WRITE_TIMEOUT);
858 info.new_connection = !connection->reported(); 886 info.new_connection = !connection->reported();
859 connection->set_reported(true); 887 connection->set_reported(true);
860 info.rtt = connection->rtt(); 888 info.rtt = connection->rtt();
(...skipping 23 matching lines...) Expand all
884 // Begin allocate (or immediately re-allocate, if MSG_ALLOCATE pending) 912 // Begin allocate (or immediately re-allocate, if MSG_ALLOCATE pending)
885 void P2PTransportChannel::Allocate() { 913 void P2PTransportChannel::Allocate() {
886 // Time for a new allocator, lets make sure we have a signalling channel 914 // Time for a new allocator, lets make sure we have a signalling channel
887 // to communicate candidates through first. 915 // to communicate candidates through first.
888 waiting_for_signaling_ = true; 916 waiting_for_signaling_ = true;
889 SignalRequestSignaling(this); 917 SignalRequestSignaling(this);
890 } 918 }
891 919
892 // Monitor connection states. 920 // Monitor connection states.
893 void P2PTransportChannel::UpdateConnectionStates() { 921 void P2PTransportChannel::UpdateConnectionStates() {
894 uint32 now = rtc::Time();
895
896 // We need to copy the list of connections since some may delete themselves 922 // We need to copy the list of connections since some may delete themselves
897 // when we call UpdateState. 923 // when we call UpdateState.
924 uint32 now = rtc::Time();
898 for (uint32 i = 0; i < connections_.size(); ++i) 925 for (uint32 i = 0; i < connections_.size(); ++i)
899 connections_[i]->UpdateState(now); 926 connections_[i]->UpdateState(now);
900 } 927 }
901 928
902 // Prepare for best candidate sorting. 929 // Prepare for best candidate sorting.
903 void P2PTransportChannel::RequestSort() { 930 void P2PTransportChannel::RequestSort() {
904 if (!sort_dirty_) { 931 if (!sort_dirty_) {
905 worker_thread_->Post(this, MSG_SORT); 932 worker_thread_->Post(this, MSG_SORT);
906 sort_dirty_ = true; 933 sort_dirty_ = true;
907 } 934 }
(...skipping 10 matching lines...) Expand all
918 945
919 // Any changes after this point will require a re-sort. 946 // Any changes after this point will require a re-sort.
920 sort_dirty_ = false; 947 sort_dirty_ = false;
921 948
922 // Find the best alternative connection by sorting. It is important to note 949 // Find the best alternative connection by sorting. It is important to note
923 // that amongst equal preference, writable connections, this will choose the 950 // that amongst equal preference, writable connections, this will choose the
924 // one whose estimated latency is lowest. So it is the only one that we 951 // one whose estimated latency is lowest. So it is the only one that we
925 // need to consider switching to. 952 // need to consider switching to.
926 ConnectionCompare cmp; 953 ConnectionCompare cmp;
927 std::stable_sort(connections_.begin(), connections_.end(), cmp); 954 std::stable_sort(connections_.begin(), connections_.end(), cmp);
928 LOG(LS_VERBOSE) << "Sorting available connections:"; 955 LOG(LS_VERBOSE) << "Sorting " << connections_.size()
956 << " available connections:";
929 for (uint32 i = 0; i < connections_.size(); ++i) { 957 for (uint32 i = 0; i < connections_.size(); ++i) {
930 LOG(LS_VERBOSE) << connections_[i]->ToString(); 958 LOG(LS_VERBOSE) << connections_[i]->ToString();
931 } 959 }
932 960
933 Connection* top_connection = 961 Connection* top_connection =
934 (connections_.size() > 0) ? connections_[0] : nullptr; 962 (connections_.size() > 0) ? connections_[0] : nullptr;
935 963
936 // If necessary, switch to the new choice. 964 // If necessary, switch to the new choice.
937 // Note that |top_connection| doesn't have to be writable to become the best 965 // Note that |top_connection| doesn't have to be writable to become the best
938 // connection although it will have higher priority if it is writable. 966 // connection although it will have higher priority if it is writable.
939 // The controlled side can switch the best connection only if the current 967 if (ShouldSwitch(best_connection_, top_connection, ice_role_)) {
940 // |best connection_| has not been nominated by the controlling side yet.
941 if ((ice_role_ == ICEROLE_CONTROLLING || !best_nominated_connection()) &&
942 ShouldSwitch(best_connection_, top_connection)) {
943 LOG(LS_INFO) << "Switching best connection: " << top_connection->ToString(); 968 LOG(LS_INFO) << "Switching best connection: " << top_connection->ToString();
944 SwitchBestConnectionTo(top_connection); 969 SwitchBestConnectionTo(top_connection);
945 } 970 }
946 971
947 // Controlled side can prune only if the best connection has been nominated. 972 // Controlled side can prune only if the best connection has been nominated.
948 // because otherwise it may delete the connection that will be selected by 973 // because otherwise it may delete the connection that will be selected by
949 // the controlling side. 974 // the controlling side.
950 if (ice_role_ == ICEROLE_CONTROLLING || best_nominated_connection()) { 975 if (ice_role_ == ICEROLE_CONTROLLING || best_nominated_connection()) {
951 PruneConnections(); 976 PruneConnections();
952 } 977 }
(...skipping 27 matching lines...) Expand all
980 : nullptr; 1005 : nullptr;
981 } 1006 }
982 1007
983 void P2PTransportChannel::PruneConnections() { 1008 void P2PTransportChannel::PruneConnections() {
984 // We can prune any connection for which there is a connected, writable 1009 // We can prune any connection for which there is a connected, writable
985 // connection on the same network with better or equal priority. We leave 1010 // connection on the same network with better or equal priority. We leave
986 // those with better priority just in case they become writable later (at 1011 // those with better priority just in case they become writable later (at
987 // which point, we would prune out the current best connection). We leave 1012 // which point, we would prune out the current best connection). We leave
988 // connections on other networks because they may not be using the same 1013 // connections on other networks because they may not be using the same
989 // resources and they may represent very distinct paths over which we can 1014 // resources and they may represent very distinct paths over which we can
990 // switch. If the |primier| connection is not connected, we may be 1015 // switch. If the |premier| connection is not connected, we may be
991 // reconnecting a TCP connection and temporarily do not prune connections in 1016 // reconnecting a TCP connection and temporarily do not prune connections in
992 // this network. See the big comment in CompareConnections. 1017 // this network. See the big comment in CompareConnections.
993 1018
994 // Get a list of the networks that we are using. 1019 // Get a list of the networks that we are using.
995 std::set<rtc::Network*> networks; 1020 std::set<rtc::Network*> networks;
996 for (const Connection* conn : connections_) { 1021 for (const Connection* conn : connections_) {
997 networks.insert(conn->port()->Network()); 1022 networks.insert(conn->port()->Network());
998 } 1023 }
999 for (rtc::Network* network : networks) { 1024 for (rtc::Network* network : networks) {
1000 Connection* primier = GetBestConnectionOnNetwork(network); 1025 Connection* premier = GetBestConnectionOnNetwork(network);
1001 if (!(primier && primier->writable() && primier->connected())) { 1026 if (!(premier && premier->writable() && premier->connected())) {
1002 continue; 1027 continue;
1003 } 1028 }
1004 1029 premier->Unprune(); // Un-prune the premier connection.
1005 for (Connection* conn : connections_) { 1030 for (Connection* conn : connections_) {
1006 if ((conn != primier) && (conn->port()->Network() == network) && 1031 if ((conn != premier) && (conn->port()->Network() == network) &&
1007 (CompareConnectionCandidates(primier, conn) >= 0)) { 1032 (CompareConnectionCandidates(premier, conn) >= 0)) {
1008 conn->Prune(); 1033 conn->Prune();
1009 } 1034 }
1010 } 1035 }
1011 } 1036 }
1012 } 1037 }
1013 1038
1014 // Track the best connection, and let listeners know 1039 // Track the best connection, and let listeners know
1015 void P2PTransportChannel::SwitchBestConnectionTo(Connection* conn) { 1040 void P2PTransportChannel::SwitchBestConnectionTo(Connection* conn) {
1016 // Note: if conn is NULL, the previous best_connection_ has been destroyed, 1041 // Note: if conn is NULL, the previous best_connection_ has been destroyed,
1017 // so don't use it. 1042 // so don't use it.
1018 Connection* old_best_connection = best_connection_; 1043 Connection* old_best_connection = best_connection_;
1019 best_connection_ = conn; 1044 best_connection_ = conn;
1020 if (best_connection_) { 1045 if (best_connection_) {
1021 if (old_best_connection) { 1046 if (old_best_connection) {
1022 LOG_J(LS_INFO, this) << "Previous best connection: " 1047 LOG_J(LS_INFO, this) << "Previous best connection: "
1023 << old_best_connection->ToString(); 1048 << old_best_connection->ToString();
1024 } 1049 }
1025 LOG_J(LS_INFO, this) << "New best connection: " 1050 LOG_J(LS_INFO, this) << "New best connection: "
1026 << best_connection_->ToString(); 1051 << best_connection_->ToString();
1027 SignalRouteChange(this, best_connection_->remote_candidate()); 1052 SignalRouteChange(this, best_connection_->remote_candidate());
1028 set_receiving(best_connection_->receiving()); 1053 set_receiving(best_connection_->receiving());
1029 } else { 1054 } else {
1030 LOG_J(LS_INFO, this) << "No best connection"; 1055 LOG_J(LS_INFO, this) << "No best connection";
1031 } 1056 }
1032 } 1057 }
1033 1058
1034 void P2PTransportChannel::UpdateChannelState() { 1059 void P2PTransportChannel::UpdateChannelState() {
1035 // The Handle* functions already set the writable state. We'll just double- 1060 // The Handle* functions already set the writable state. We'll just double-
1036 // check it here. 1061 // check it here.
1037 bool writable = ((best_connection_ != NULL) && 1062 bool writable = best_connection_ && best_connection_->writable();
1038 (best_connection_->write_state() ==
1039 Connection::STATE_WRITABLE));
1040 ASSERT(writable == this->writable()); 1063 ASSERT(writable == this->writable());
1041 if (writable != this->writable()) 1064 if (writable != this->writable())
1042 LOG(LS_ERROR) << "UpdateChannelState: writable state mismatch"; 1065 LOG(LS_ERROR) << "UpdateChannelState: writable state mismatch";
1043 1066
1044 // TODO(honghaiz): The channel receiving state is set in OnCheckReceiving. 1067 bool receiving =
1045 // Will revisit in a subsequent code change. 1068 std::any_of(connections_.begin(), connections_.end(),
1069 [](const Connection* conn) { return conn->receiving(); });
1070 set_receiving(receiving);
1046 } 1071 }
1047 1072
1048 // 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
1049 // was writable, go into the writable state. 1074 // was writable, go into the writable state.
1050 void P2PTransportChannel::HandleWritable() { 1075 void P2PTransportChannel::HandleWritable() {
1051 ASSERT(worker_thread_ == rtc::Thread::Current()); 1076 ASSERT(worker_thread_ == rtc::Thread::Current());
1052 if (!writable()) { 1077 if (!writable()) {
1053 for (uint32 i = 0; i < allocator_sessions_.size(); ++i) { 1078 for (uint32 i = 0; i < allocator_sessions_.size(); ++i) {
1054 if (allocator_sessions_[i]->IsGettingPorts()) { 1079 if (allocator_sessions_[i]->IsGettingPorts()) {
1055 allocator_sessions_[i]->StopGettingPorts(); 1080 allocator_sessions_[i]->StopGettingPorts();
(...skipping 12 matching lines...) Expand all
1068 was_writable_ = false; 1093 was_writable_ = false;
1069 set_writable(false); 1094 set_writable(false);
1070 } 1095 }
1071 } 1096 }
1072 1097
1073 void P2PTransportChannel::HandleAllTimedOut() { 1098 void P2PTransportChannel::HandleAllTimedOut() {
1074 // Currently we are treating this as channel not writable. 1099 // Currently we are treating this as channel not writable.
1075 HandleNotWritable(); 1100 HandleNotWritable();
1076 } 1101 }
1077 1102
1103 bool P2PTransportChannel::Weak() const {
1104 return !(best_connection_ && best_connection_->receiving() && writable());
1105 }
1106
1078 // 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
1079 // list (later we will mark it best). 1108 // list (later we will mark it best).
1080 Connection* P2PTransportChannel::GetBestConnectionOnNetwork( 1109 Connection* P2PTransportChannel::GetBestConnectionOnNetwork(
1081 rtc::Network* network) const { 1110 rtc::Network* network) const {
1082 // If the best connection is on this network, then it wins. 1111 // If the best connection is on this network, then it wins.
1083 if (best_connection_ && (best_connection_->port()->Network() == network)) 1112 if (best_connection_ && (best_connection_->port()->Network() == network))
1084 return best_connection_; 1113 return best_connection_;
1085 1114
1086 // Otherwise, we return the top-most in sorted order. 1115 // Otherwise, we return the top-most in sorted order.
1087 for (uint32 i = 0; i < connections_.size(); ++i) { 1116 for (uint32 i = 0; i < connections_.size(); ++i) {
1088 if (connections_[i]->port()->Network() == network) 1117 if (connections_[i]->port()->Network() == network)
1089 return connections_[i]; 1118 return connections_[i];
1090 } 1119 }
1091 1120
1092 return NULL; 1121 return NULL;
1093 } 1122 }
1094 1123
1095 // Handle any queued up requests 1124 // Handle any queued up requests
1096 void P2PTransportChannel::OnMessage(rtc::Message *pmsg) { 1125 void P2PTransportChannel::OnMessage(rtc::Message *pmsg) {
1097 switch (pmsg->message_id) { 1126 switch (pmsg->message_id) {
1098 case MSG_SORT: 1127 case MSG_SORT:
1099 OnSort(); 1128 OnSort();
1100 break; 1129 break;
1101 case MSG_PING: 1130 case MSG_CHECK_AND_PING:
1102 OnPing(); 1131 OnCheckAndPing();
1103 break;
1104 case MSG_CHECK_RECEIVING:
1105 OnCheckReceiving();
1106 break; 1132 break;
1107 default: 1133 default:
1108 ASSERT(false); 1134 ASSERT(false);
1109 break; 1135 break;
1110 } 1136 }
1111 } 1137 }
1112 1138
1113 // Handle queued up sort request 1139 // Handle queued up sort request
1114 void P2PTransportChannel::OnSort() { 1140 void P2PTransportChannel::OnSort() {
1115 // Resort the connections based on the new statistics. 1141 // Resort the connections based on the new statistics.
1116 SortConnections(); 1142 SortConnections();
1117 } 1143 }
1118 1144
1119 // Handle queued up ping request 1145 // Handle queued up check-and-ping request
1120 void P2PTransportChannel::OnPing() { 1146 void P2PTransportChannel::OnCheckAndPing() {
1121 // Make sure the states of the connections are up-to-date (since this affects 1147 // Make sure the states of the connections are up-to-date (since this affects
1122 // which ones are pingable). 1148 // which ones are pingable).
1123 UpdateConnectionStates(); 1149 UpdateConnectionStates();
1124 1150 // When the best connection is either not receiving or not writable,
1125 // Find the oldest pingable connection and have it do a ping. 1151 // switch to weak ping delay.
1126 Connection* conn = FindNextPingableConnection(); 1152 int ping_delay = Weak() ? WEAK_PING_DELAY : STRONG_PING_DELAY;
1127 if (conn) 1153 if (rtc::Time() >= last_ping_sent_ + ping_delay) {
1128 PingConnection(conn); 1154 Connection* conn = FindNextPingableConnection();
1129 1155 if (conn) {
1130 // Post ourselves a message to perform the next ping. 1156 PingConnection(conn);
1131 uint32 delay = writable() ? WRITABLE_DELAY : UNWRITABLE_DELAY; 1157 }
1132 thread()->PostDelayed(delay, this, MSG_PING);
1133 }
1134
1135 void P2PTransportChannel::OnCheckReceiving() {
1136 if (best_connection_) {
1137 bool receiving = rtc::Time() <=
1138 best_connection_->last_received() + receiving_timeout_;
1139 set_receiving(receiving);
1140 } 1158 }
1141 1159 int check_delay = std::min(ping_delay, check_receiving_delay_);
1142 thread()->PostDelayed(check_receiving_delay_, this, MSG_CHECK_RECEIVING); 1160 thread()->PostDelayed(check_delay, this, MSG_CHECK_AND_PING);
1143 } 1161 }
1144 1162
1145 // Is the connection in a state for us to even consider pinging the other side? 1163 // Is the connection in a state for us to even consider pinging the other side?
1146 // We consider a connection pingable even if it's not connected because that's 1164 // We consider a connection pingable even if it's not connected because that's
1147 // how a TCP connection is kicked into reconnecting on the active side. 1165 // how a TCP connection is kicked into reconnecting on the active side.
1148 bool P2PTransportChannel::IsPingable(Connection* conn) { 1166 bool P2PTransportChannel::IsPingable(Connection* conn) {
1149 const Candidate& remote = conn->remote_candidate(); 1167 const Candidate& remote = conn->remote_candidate();
1150 // We should never get this far with an empty remote ufrag. 1168 // We should never get this far with an empty remote ufrag.
1151 ASSERT(!remote.username().empty()); 1169 ASSERT(!remote.username().empty());
1152 if (remote.username().empty() || remote.password().empty()) { 1170 if (remote.username().empty() || remote.password().empty()) {
1153 // If we don't have an ICE ufrag and pwd, there's no way we can ping. 1171 // If we don't have an ICE ufrag and pwd, there's no way we can ping.
1154 return false; 1172 return false;
1155 } 1173 }
1156 1174
1157 // An never connected connection cannot be written to at all, so pinging is 1175 // An never connected connection cannot be written to at all, so pinging is
1158 // out of the question. However, if it has become WRITABLE, it is in the 1176 // out of the question. However, if it has become WRITABLE, it is in the
1159 // reconnecting state so ping is needed. 1177 // reconnecting state so ping is needed.
1160 if (!conn->connected() && !conn->writable()) { 1178 if (!conn->connected() && !conn->writable()) {
1161 return false; 1179 return false;
1162 } 1180 }
1163 1181
1164 // If the channel is not writable, ping all candidates. Otherwise, we only 1182 // If the channel is weak, ping all candidates. Otherwise, ping only
1165 // want to ping connections that have not timed out on writing. 1183 // un-pruned and not-write-timed-out candidates.
1166 return !writable() || conn->write_state() != Connection::STATE_WRITE_TIMEOUT; 1184 return Weak() || (!conn->pruned() && !conn->write_timed_out());
1167 } 1185 }
1168 1186
1169 // Returns the next pingable connection to ping. This will be the oldest 1187 // Returns the next pingable connection to ping. This will be the oldest
1170 // pingable connection unless we have a connected, writable connection that is 1188 // pingable connection unless we have a connected, writable connection that is
1171 // past the maximum acceptable ping delay. When reconnecting a TCP connection, 1189 // past the maximum acceptable ping delay. When reconnecting a TCP connection,
1172 // the best connection is disconnected, although still WRITABLE while 1190 // the best connection is disconnected, although still WRITABLE while
1173 // reconnecting. The newly created connection should be selected as the ping 1191 // reconnecting. The newly created connection should be selected as the ping
1174 // target to become writable instead. See the big comment in CompareConnections. 1192 // target to become writable instead. See the big comment in CompareConnections.
1175 Connection* P2PTransportChannel::FindNextPingableConnection() { 1193 Connection* P2PTransportChannel::FindNextPingableConnection() {
1176 uint32 now = rtc::Time(); 1194 uint32 now = rtc::Time();
1177 if (best_connection_ && best_connection_->connected() && 1195 if (best_connection_ && best_connection_->connected() &&
1178 (best_connection_->write_state() == Connection::STATE_WRITABLE) && 1196 best_connection_->writable() &&
1179 (best_connection_->last_ping_sent() + MAX_CURRENT_WRITABLE_DELAY <= 1197 (best_connection_->last_ping_sent() + MAX_CURRENT_WRITABLE_DELAY <=
1180 now)) { 1198 now)) {
1181 return best_connection_; 1199 return best_connection_;
1182 } 1200 }
1183 1201
1184 // First, find "triggered checks". We ping first those connections 1202 // First, find "triggered checks". We ping first those connections
1185 // that have received a ping but have not sent a ping since receiving 1203 // that have received a ping but have not sent a ping since receiving
1186 // it (last_received_ping > last_sent_ping). But we shouldn't do 1204 // it (last_received_ping > last_sent_ping). But we shouldn't do
1187 // triggered checks if the connection is already writable. 1205 // triggered checks if the connection is already writable.
1188 Connection* oldest_needing_triggered_check = nullptr; 1206 Connection* oldest_needing_triggered_check = nullptr;
(...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after
1229 bool use_candidate = false; 1247 bool use_candidate = false;
1230 if (remote_ice_mode_ == ICEMODE_FULL && ice_role_ == ICEROLE_CONTROLLING) { 1248 if (remote_ice_mode_ == ICEMODE_FULL && ice_role_ == ICEROLE_CONTROLLING) {
1231 use_candidate = (conn == best_connection_) || 1249 use_candidate = (conn == best_connection_) ||
1232 (best_connection_ == NULL) || 1250 (best_connection_ == NULL) ||
1233 (!best_connection_->writable()) || 1251 (!best_connection_->writable()) ||
1234 (conn->priority() > best_connection_->priority()); 1252 (conn->priority() > best_connection_->priority());
1235 } else if (remote_ice_mode_ == ICEMODE_LITE && conn == best_connection_) { 1253 } else if (remote_ice_mode_ == ICEMODE_LITE && conn == best_connection_) {
1236 use_candidate = best_connection_->writable(); 1254 use_candidate = best_connection_->writable();
1237 } 1255 }
1238 conn->set_use_candidate_attr(use_candidate); 1256 conn->set_use_candidate_attr(use_candidate);
1239 conn->Ping(rtc::Time()); 1257 last_ping_sent_ = rtc::Time();
1258 conn->Ping(last_ping_sent_);
1240 } 1259 }
1241 1260
1242 // When a connection's state changes, we need to figure out who to use as 1261 // When a connection's state changes, we need to figure out who to use as
1243 // the best connection again. It could have become usable, or become unusable. 1262 // the best connection again. It could have become usable, or become unusable.
1244 void P2PTransportChannel::OnConnectionStateChange(Connection* connection) { 1263 void P2PTransportChannel::OnConnectionStateChange(Connection* connection) {
1245 ASSERT(worker_thread_ == rtc::Thread::Current()); 1264 ASSERT(worker_thread_ == rtc::Thread::Current());
1246 1265
1247 // Update the best connection if the state change is from pending best 1266 // Update the best connection if the state change is from pending best
1248 // connection and role is controlled. 1267 // connection and role is controlled.
1249 if (ice_role_ == ICEROLE_CONTROLLED) { 1268 if (ice_role_ == ICEROLE_CONTROLLED) {
(...skipping 66 matching lines...) Expand 10 before | Expand all | Expand 10 after
1316 const rtc::PacketTime& packet_time) { 1335 const rtc::PacketTime& packet_time) {
1317 ASSERT(worker_thread_ == rtc::Thread::Current()); 1336 ASSERT(worker_thread_ == rtc::Thread::Current());
1318 1337
1319 // Do not deliver, if packet doesn't belong to the correct transport channel. 1338 // Do not deliver, if packet doesn't belong to the correct transport channel.
1320 if (!FindConnection(connection)) 1339 if (!FindConnection(connection))
1321 return; 1340 return;
1322 1341
1323 // Let the client know of an incoming packet 1342 // Let the client know of an incoming packet
1324 SignalReadPacket(this, data, len, packet_time, 0); 1343 SignalReadPacket(this, data, len, packet_time, 0);
1325 1344
1326 // May need to switch the sending connection based on the receiving media path 1345 // If the receiving connection is different from the sending connection,
1327 // if this is the controlled side. 1346 // may need to switch the sending connection based on the receiving media
1328 if (ice_role_ == ICEROLE_CONTROLLED && !best_nominated_connection() && 1347 // path if this is the controlled side. It will not switch if the sending
1329 connection->writable() && best_connection_ != connection) { 1348 // connection is nominated but the receiving connection is not nominated.
1349 if (best_connection_ != connection && ice_role_ == ICEROLE_CONTROLLED &&
1350 (!best_nominated_connection() || connection->nominated()) &&
1351 connection->writable()) {
1330 SwitchBestConnectionTo(connection); 1352 SwitchBestConnectionTo(connection);
1331 } 1353 }
1332 } 1354 }
1333 1355
1334 void P2PTransportChannel::OnReadyToSend(Connection* connection) { 1356 void P2PTransportChannel::OnReadyToSend(Connection* connection) {
1335 if (connection == best_connection_ && writable()) { 1357 if (connection == best_connection_ && writable()) {
1336 SignalReadyToSend(this); 1358 SignalReadyToSend(this);
1337 } 1359 }
1338 } 1360 }
1339 1361
1340 } // namespace cricket 1362 } // namespace cricket
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698