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

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

Issue 1455033004: Ping backup connection at a slower rate (Closed) Base URL: https://chromium.googlesource.com/external/webrtc@master
Patch Set: Created 5 years 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
« no previous file with comments | « webrtc/p2p/base/p2ptransportchannel.h ('k') | webrtc/p2p/base/p2ptransportchannel_unittest.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 /* 1 /*
2 * Copyright 2004 The WebRTC Project Authors. All rights reserved. 2 * Copyright 2004 The WebRTC Project Authors. All rights reserved.
3 * 3 *
4 * Use of this source code is governed by a BSD-style license 4 * Use of this source code is governed by a BSD-style license
5 * that can be found in the LICENSE file in the root of the source 5 * that can be found in the LICENSE file in the root of the source
6 * tree. An additional intellectual property rights grant can be found 6 * tree. An additional intellectual property rights grant can be found
7 * in the file PATENTS. All contributing project authors may 7 * in the file PATENTS. All contributing project authors may
8 * be found in the AUTHORS file in the root of the source tree. 8 * be found in the AUTHORS file in the root of the source tree.
9 */ 9 */
10 10
(...skipping 169 matching lines...) Expand 10 before | Expand all | Expand 10 after
180 } // unnamed namespace 180 } // unnamed namespace
181 181
182 namespace cricket { 182 namespace cricket {
183 183
184 // When the socket is unwritable, we will use 10 Kbps (ignoring IP+UDP headers) 184 // When the socket is unwritable, we will use 10 Kbps (ignoring IP+UDP headers)
185 // for pinging. When the socket is writable, we will use only 1 Kbps because 185 // for pinging. When the socket is writable, we will use only 1 Kbps because
186 // we don't want to degrade the quality on a modem. These numbers should work 186 // we don't want to degrade the quality on a modem. These numbers should work
187 // well on a 28.8K modem, which is the slowest connection on which the voice 187 // well on a 28.8K modem, which is the slowest connection on which the voice
188 // quality is reasonable at all. 188 // quality is reasonable at all.
189 static const uint32_t PING_PACKET_SIZE = 60 * 8; 189 static const uint32_t PING_PACKET_SIZE = 60 * 8;
190 // TODO(honghaiz): Change the word DELAY to INTERVAL whenever appropriate.
190 // STRONG_PING_DELAY (480ms) is applied when the best connection is both 191 // STRONG_PING_DELAY (480ms) is applied when the best connection is both
191 // writable and receiving. 192 // writable and receiving.
192 static const uint32_t STRONG_PING_DELAY = 1000 * PING_PACKET_SIZE / 1000; 193 static const uint32_t STRONG_PING_DELAY = 1000 * PING_PACKET_SIZE / 1000;
193 // WEAK_PING_DELAY (48ms) is applied when the best connection is either not 194 // WEAK_PING_DELAY (48ms) is applied when the best connection is either not
194 // writable or not receiving. 195 // writable or not receiving.
195 const uint32_t WEAK_PING_DELAY = 1000 * PING_PACKET_SIZE / 10000; 196 const uint32_t WEAK_PING_DELAY = 1000 * PING_PACKET_SIZE / 10000;
196 197
197 // If the current best connection is both writable and receiving, then we will 198 // If the current best connection is both writable and receiving, then we will
198 // also try hard to make sure it is pinged at this rate (a little less than 199 // also try hard to make sure it is pinged at this rate (a little less than
199 // 2 * STRONG_PING_DELAY). 200 // 2 * STRONG_PING_DELAY).
200 static const uint32_t MAX_CURRENT_STRONG_DELAY = 900; 201 static const uint32_t MAX_CURRENT_STRONG_DELAY = 900;
201 202
202 static const int MIN_CHECK_RECEIVING_DELAY = 50; // ms 203 static const int MIN_CHECK_RECEIVING_DELAY = 50; // ms
203 204
204
205 P2PTransportChannel::P2PTransportChannel(const std::string& transport_name, 205 P2PTransportChannel::P2PTransportChannel(const std::string& transport_name,
206 int component, 206 int component,
207 P2PTransport* transport, 207 P2PTransport* transport,
208 PortAllocator* allocator) 208 PortAllocator* allocator)
209 : TransportChannelImpl(transport_name, component), 209 : TransportChannelImpl(transport_name, component),
210 transport_(transport), 210 transport_(transport),
211 allocator_(allocator), 211 allocator_(allocator),
212 worker_thread_(rtc::Thread::Current()), 212 worker_thread_(rtc::Thread::Current()),
213 incoming_only_(false), 213 incoming_only_(false),
214 error_(0), 214 error_(0),
215 best_connection_(NULL), 215 best_connection_(NULL),
216 pending_best_connection_(NULL), 216 pending_best_connection_(NULL),
217 sort_dirty_(false), 217 sort_dirty_(false),
218 remote_ice_mode_(ICEMODE_FULL), 218 remote_ice_mode_(ICEMODE_FULL),
219 ice_role_(ICEROLE_UNKNOWN), 219 ice_role_(ICEROLE_UNKNOWN),
220 tiebreaker_(0), 220 tiebreaker_(0),
221 remote_candidate_generation_(0), 221 remote_candidate_generation_(0),
222 gathering_state_(kIceGatheringNew), 222 gathering_state_(kIceGatheringNew),
223 check_receiving_delay_(MIN_CHECK_RECEIVING_DELAY * 5), 223 check_receiving_delay_(MIN_CHECK_RECEIVING_DELAY * 5),
224 receiving_timeout_(MIN_CHECK_RECEIVING_DELAY * 50) { 224 receiving_timeout_(MIN_CHECK_RECEIVING_DELAY * 50),
225 backup_connection_ping_interval_(0) {
225 uint32_t weak_ping_delay = ::strtoul( 226 uint32_t weak_ping_delay = ::strtoul(
226 webrtc::field_trial::FindFullName("WebRTC-StunInterPacketDelay").c_str(), 227 webrtc::field_trial::FindFullName("WebRTC-StunInterPacketDelay").c_str(),
227 nullptr, 10); 228 nullptr, 10);
228 if (weak_ping_delay) { 229 if (weak_ping_delay) {
229 weak_ping_delay_ = weak_ping_delay; 230 weak_ping_delay_ = weak_ping_delay;
230 } 231 }
231 } 232 }
232 233
233 P2PTransportChannel::~P2PTransportChannel() { 234 P2PTransportChannel::~P2PTransportChannel() {
234 ASSERT(worker_thread_ == rtc::Thread::Current()); 235 ASSERT(worker_thread_ == rtc::Thread::Current());
(...skipping 54 matching lines...) Expand 10 before | Expand all | Expand 10 after
289 ASSERT(worker_thread_ == rtc::Thread::Current()); 290 ASSERT(worker_thread_ == rtc::Thread::Current());
290 if (!ports_.empty()) { 291 if (!ports_.empty()) {
291 LOG(LS_ERROR) 292 LOG(LS_ERROR)
292 << "Attempt to change tiebreaker after Port has been allocated."; 293 << "Attempt to change tiebreaker after Port has been allocated.";
293 return; 294 return;
294 } 295 }
295 296
296 tiebreaker_ = tiebreaker; 297 tiebreaker_ = tiebreaker;
297 } 298 }
298 299
300 TransportChannelState P2PTransportChannel::GetState() const {
301 return state_;
302 }
303
299 // A channel is considered ICE completed once there is at most one active 304 // A channel is considered ICE completed once there is at most one active
300 // connection per network and at least one active connection. 305 // connection per network and at least one active connection.
301 TransportChannelState P2PTransportChannel::GetState() const { 306 TransportChannelState P2PTransportChannel::ComputeState() const {
302 if (!had_connection_) { 307 if (!had_connection_) {
303 return TransportChannelState::STATE_INIT; 308 return TransportChannelState::STATE_INIT;
304 } 309 }
305 310
306 std::vector<Connection*> active_connections; 311 std::vector<Connection*> active_connections;
307 for (Connection* connection : connections_) { 312 for (Connection* connection : connections_) {
308 if (connection->active()) { 313 if (connection->active()) {
309 active_connections.push_back(connection); 314 active_connections.push_back(connection);
310 } 315 }
311 } 316 }
(...skipping 53 matching lines...) Expand 10 before | Expand all | Expand 10 after
365 } 370 }
366 371
367 void P2PTransportChannel::SetRemoteIceMode(IceMode mode) { 372 void P2PTransportChannel::SetRemoteIceMode(IceMode mode) {
368 remote_ice_mode_ = mode; 373 remote_ice_mode_ = mode;
369 } 374 }
370 375
371 void P2PTransportChannel::SetIceConfig(const IceConfig& config) { 376 void P2PTransportChannel::SetIceConfig(const IceConfig& config) {
372 gather_continually_ = config.gather_continually; 377 gather_continually_ = config.gather_continually;
373 LOG(LS_INFO) << "Set gather_continually to " << gather_continually_; 378 LOG(LS_INFO) << "Set gather_continually to " << gather_continually_;
374 379
375 if (config.receiving_timeout_ms < 0) { 380 if (config.backup_connection_ping_interval >= 0 &&
376 return; 381 backup_connection_ping_interval_ !=
382 config.backup_connection_ping_interval) {
383 backup_connection_ping_interval_ = config.backup_connection_ping_interval;
384 LOG(LS_INFO) << "Set backup connection ping interval to "
385 << backup_connection_ping_interval_ << " milliseconds.";
377 } 386 }
378 receiving_timeout_ = config.receiving_timeout_ms;
379 check_receiving_delay_ =
380 std::max(MIN_CHECK_RECEIVING_DELAY, receiving_timeout_ / 10);
381 387
382 for (Connection* connection : connections_) { 388 if (config.receiving_timeout_ms >= 0 &&
383 connection->set_receiving_timeout(receiving_timeout_); 389 receiving_timeout_ != config.receiving_timeout_ms) {
390 receiving_timeout_ = config.receiving_timeout_ms;
391 check_receiving_delay_ =
392 std::max(MIN_CHECK_RECEIVING_DELAY, receiving_timeout_ / 10);
393
394 for (Connection* connection : connections_) {
395 connection->set_receiving_timeout(receiving_timeout_);
396 }
397 LOG(LS_INFO) << "Set ICE receiving timeout to " << receiving_timeout_
398 << " milliseconds";
384 } 399 }
385 LOG(LS_INFO) << "Set ICE receiving timeout to " << receiving_timeout_
386 << " milliseconds";
387 } 400 }
388 401
389 // Go into the state of processing candidates, and running in general 402 // Go into the state of processing candidates, and running in general
390 void P2PTransportChannel::Connect() { 403 void P2PTransportChannel::Connect() {
391 ASSERT(worker_thread_ == rtc::Thread::Current()); 404 ASSERT(worker_thread_ == rtc::Thread::Current());
392 if (ice_ufrag_.empty() || ice_pwd_.empty()) { 405 if (ice_ufrag_.empty() || ice_pwd_.empty()) {
393 ASSERT(false); 406 ASSERT(false);
394 LOG(LS_ERROR) << "P2PTransportChannel::Connect: The ice_ufrag_ and the " 407 LOG(LS_ERROR) << "P2PTransportChannel::Connect: The ice_ufrag_ and the "
395 << "ice_pwd_ are not set."; 408 << "ice_pwd_ are not set.";
396 return; 409 return;
(...skipping 586 matching lines...) Expand 10 before | Expand all | Expand 10 after
983 } 996 }
984 997
985 // Now update the writable state of the channel with the information we have 998 // Now update the writable state of the channel with the information we have
986 // so far. 999 // so far.
987 if (all_connections_timedout) { 1000 if (all_connections_timedout) {
988 HandleAllTimedOut(); 1001 HandleAllTimedOut();
989 } 1002 }
990 1003
991 // Update the state of this channel. This method is called whenever the 1004 // Update the state of this channel. This method is called whenever the
992 // state of any connection changes, so this is a good place to do this. 1005 // state of any connection changes, so this is a good place to do this.
993 UpdateChannelState(); 1006 UpdateState();
994 } 1007 }
995 1008
996 Connection* P2PTransportChannel::best_nominated_connection() const { 1009 Connection* P2PTransportChannel::best_nominated_connection() const {
997 return (best_connection_ && best_connection_->nominated()) ? best_connection_ 1010 return (best_connection_ && best_connection_->nominated()) ? best_connection_
998 : nullptr; 1011 : nullptr;
999 } 1012 }
1000 1013
1001 void P2PTransportChannel::PruneConnections() { 1014 void P2PTransportChannel::PruneConnections() {
1002 // We can prune any connection for which there is a connected, writable 1015 // We can prune any connection for which there is a connected, writable
1003 // connection on the same network with better or equal priority. We leave 1016 // connection on the same network with better or equal priority. We leave
(...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after
1043 << old_best_connection->ToString(); 1056 << old_best_connection->ToString();
1044 } 1057 }
1045 LOG_J(LS_INFO, this) << "New best connection: " 1058 LOG_J(LS_INFO, this) << "New best connection: "
1046 << best_connection_->ToString(); 1059 << best_connection_->ToString();
1047 SignalRouteChange(this, best_connection_->remote_candidate()); 1060 SignalRouteChange(this, best_connection_->remote_candidate());
1048 } else { 1061 } else {
1049 LOG_J(LS_INFO, this) << "No best connection"; 1062 LOG_J(LS_INFO, this) << "No best connection";
1050 } 1063 }
1051 } 1064 }
1052 1065
1053 void P2PTransportChannel::UpdateChannelState() { 1066 // Warning: UpdateState should eventually be called whenever a connection
1067 // is added, deleted, or the write state of any connection changes so that the
1068 // transport controller will get the up-to-date channel state. However it
1069 // should not be called too often; in the case that multiple connection states
1070 // change, it should be called after all the connection states have changed. For
1071 // example, we call this at the end of SortConnections.
pthatcher 2015/12/02 19:18:24 Well written
1072 void P2PTransportChannel::UpdateState() {
1073 state_ = ComputeState();
1074
1054 bool writable = best_connection_ && best_connection_->writable(); 1075 bool writable = best_connection_ && best_connection_->writable();
1055 set_writable(writable); 1076 set_writable(writable);
1056 1077
1057 bool receiving = false; 1078 bool receiving = false;
1058 for (const Connection* connection : connections_) { 1079 for (const Connection* connection : connections_) {
1059 if (connection->receiving()) { 1080 if (connection->receiving()) {
1060 receiving = true; 1081 receiving = true;
1061 break; 1082 break;
1062 } 1083 }
1063 } 1084 }
(...skipping 79 matching lines...) Expand 10 before | Expand all | Expand 10 after
1143 if (rtc::Time() >= last_ping_sent_ms_ + ping_delay) { 1164 if (rtc::Time() >= last_ping_sent_ms_ + ping_delay) {
1144 Connection* conn = FindNextPingableConnection(); 1165 Connection* conn = FindNextPingableConnection();
1145 if (conn) { 1166 if (conn) {
1146 PingConnection(conn); 1167 PingConnection(conn);
1147 } 1168 }
1148 } 1169 }
1149 int check_delay = std::min(ping_delay, check_receiving_delay_); 1170 int check_delay = std::min(ping_delay, check_receiving_delay_);
1150 thread()->PostDelayed(check_delay, this, MSG_CHECK_AND_PING); 1171 thread()->PostDelayed(check_delay, this, MSG_CHECK_AND_PING);
1151 } 1172 }
1152 1173
1174 // A connection is considered a backup connection if the channel state
1175 // is completed, the connection is not the best connection and it is active.
1176 bool P2PTransportChannel::IsBackupConnection(Connection* conn) const {
1177 return state_ == STATE_COMPLETED && conn != best_connection_ &&
1178 conn->active();
1179 }
1180
1153 // Is the connection in a state for us to even consider pinging the other side? 1181 // Is the connection in a state for us to even consider pinging the other side?
1154 // We consider a connection pingable even if it's not connected because that's 1182 // We consider a connection pingable even if it's not connected because that's
1155 // how a TCP connection is kicked into reconnecting on the active side. 1183 // how a TCP connection is kicked into reconnecting on the active side.
1156 bool P2PTransportChannel::IsPingable(Connection* conn) { 1184 bool P2PTransportChannel::IsPingable(Connection* conn, uint32_t now) {
1157 const Candidate& remote = conn->remote_candidate(); 1185 const Candidate& remote = conn->remote_candidate();
1158 // We should never get this far with an empty remote ufrag. 1186 // We should never get this far with an empty remote ufrag.
1159 ASSERT(!remote.username().empty()); 1187 ASSERT(!remote.username().empty());
1160 if (remote.username().empty() || remote.password().empty()) { 1188 if (remote.username().empty() || remote.password().empty()) {
1161 // If we don't have an ICE ufrag and pwd, there's no way we can ping. 1189 // If we don't have an ICE ufrag and pwd, there's no way we can ping.
1162 return false; 1190 return false;
1163 } 1191 }
1164 1192
1165 // An never connected connection cannot be written to at all, so pinging is 1193 // An never connected connection cannot be written to at all, so pinging is
1166 // out of the question. However, if it has become WRITABLE, it is in the 1194 // out of the question. However, if it has become WRITABLE, it is in the
1167 // reconnecting state so ping is needed. 1195 // reconnecting state so ping is needed.
1168 if (!conn->connected() && !conn->writable()) { 1196 if (!conn->connected() && !conn->writable()) {
1169 return false; 1197 return false;
1170 } 1198 }
1171 1199
1172 // If the channel is weak, ping all candidates. Otherwise, we only 1200 // If the channel is weakly connected, ping all connections.
1173 // want to ping connections that have not timed out on writing. 1201 if (weak()) {
1174 return weak() || conn->write_state() != Connection::STATE_WRITE_TIMEOUT; 1202 return true;
1203 }
1204
1205 // Always ping active connections regardless whether the channel is completed
1206 // or not, but backup connections are pinged at a slower rate.
1207 if (IsBackupConnection(conn)) {
1208 return (now >= conn->last_ping_response_received() +
1209 backup_connection_ping_interval_);
1210 }
1211 return conn->active();
1175 } 1212 }
1176 1213
1177 // Returns the next pingable connection to ping. This will be the oldest 1214 // Returns the next pingable connection to ping. This will be the oldest
1178 // pingable connection unless we have a connected, writable connection that is 1215 // pingable connection unless we have a connected, writable connection that is
1179 // past the maximum acceptable ping delay. When reconnecting a TCP connection, 1216 // past the maximum acceptable ping delay. When reconnecting a TCP connection,
1180 // the best connection is disconnected, although still WRITABLE while 1217 // the best connection is disconnected, although still WRITABLE while
1181 // reconnecting. The newly created connection should be selected as the ping 1218 // reconnecting. The newly created connection should be selected as the ping
1182 // target to become writable instead. See the big comment in CompareConnections. 1219 // target to become writable instead. See the big comment in CompareConnections.
1183 Connection* P2PTransportChannel::FindNextPingableConnection() { 1220 Connection* P2PTransportChannel::FindNextPingableConnection() {
1184 uint32_t now = rtc::Time(); 1221 uint32_t now = rtc::Time();
1185 if (best_connection_ && best_connection_->connected() && 1222 if (best_connection_ && best_connection_->connected() &&
1186 best_connection_->writable() && 1223 best_connection_->writable() &&
1187 (best_connection_->last_ping_sent() + MAX_CURRENT_STRONG_DELAY <= now)) { 1224 (best_connection_->last_ping_sent() + MAX_CURRENT_STRONG_DELAY <= now)) {
1188 return best_connection_; 1225 return best_connection_;
1189 } 1226 }
1190 1227
1191 // First, find "triggered checks". We ping first those connections 1228 // First, find "triggered checks". We ping first those connections
1192 // that have received a ping but have not sent a ping since receiving 1229 // that have received a ping but have not sent a ping since receiving
1193 // it (last_received_ping > last_sent_ping). But we shouldn't do 1230 // it (last_received_ping > last_sent_ping). But we shouldn't do
1194 // triggered checks if the connection is already writable. 1231 // triggered checks if the connection is already writable.
1195 Connection* oldest_needing_triggered_check = nullptr; 1232 Connection* oldest_needing_triggered_check = nullptr;
1196 Connection* oldest = nullptr; 1233 Connection* oldest = nullptr;
1197 for (Connection* conn : connections_) { 1234 for (Connection* conn : connections_) {
1198 if (!IsPingable(conn)) { 1235 if (!IsPingable(conn, now)) {
1199 continue; 1236 continue;
1200 } 1237 }
1201 bool needs_triggered_check = 1238 bool needs_triggered_check =
1202 (!conn->writable() && 1239 (!conn->writable() &&
1203 conn->last_ping_received() > conn->last_ping_sent()); 1240 conn->last_ping_received() > conn->last_ping_sent());
1204 if (needs_triggered_check && 1241 if (needs_triggered_check &&
1205 (!oldest_needing_triggered_check || 1242 (!oldest_needing_triggered_check ||
1206 (conn->last_ping_received() < 1243 (conn->last_ping_received() <
1207 oldest_needing_triggered_check->last_ping_received()))) { 1244 oldest_needing_triggered_check->last_ping_received()))) {
1208 oldest_needing_triggered_check = conn; 1245 oldest_needing_triggered_check = conn;
(...skipping 91 matching lines...) Expand 10 before | Expand all | Expand 10 after
1300 // The call to SortConnections will pick a new one. It looks at the current 1337 // The call to SortConnections will pick a new one. It looks at the current
1301 // best connection in order to avoid switching between fairly similar ones. 1338 // best connection in order to avoid switching between fairly similar ones.
1302 // Since this connection is no longer an option, we can just set best to NULL 1339 // Since this connection is no longer an option, we can just set best to NULL
1303 // and re-choose a best assuming that there was no best connection. 1340 // and re-choose a best assuming that there was no best connection.
1304 if (best_connection_ == connection) { 1341 if (best_connection_ == connection) {
1305 LOG(LS_INFO) << "Best connection destroyed. Will choose a new one."; 1342 LOG(LS_INFO) << "Best connection destroyed. Will choose a new one.";
1306 SwitchBestConnectionTo(NULL); 1343 SwitchBestConnectionTo(NULL);
1307 RequestSort(); 1344 RequestSort();
1308 } 1345 }
1309 1346
1347 UpdateState();
1348 // SignalConnectionRemoved should be called after the channel state is
1349 // updated because the receiver of the event may access the channel state.
1310 SignalConnectionRemoved(this); 1350 SignalConnectionRemoved(this);
1311 } 1351 }
1312 1352
1313 // When a port is destroyed remove it from our list of ports to use for 1353 // When a port is destroyed remove it from our list of ports to use for
1314 // connection attempts. 1354 // connection attempts.
1315 void P2PTransportChannel::OnPortDestroyed(PortInterface* port) { 1355 void P2PTransportChannel::OnPortDestroyed(PortInterface* port) {
1316 ASSERT(worker_thread_ == rtc::Thread::Current()); 1356 ASSERT(worker_thread_ == rtc::Thread::Current());
1317 1357
1318 // Remove this port from the list (if we didn't drop it already). 1358 // Remove this port from the list (if we didn't drop it already).
1319 std::vector<PortInterface*>::iterator iter = 1359 std::vector<PortInterface*>::iterator iter =
(...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after
1354 SignalSentPacket(this, sent_packet); 1394 SignalSentPacket(this, sent_packet);
1355 } 1395 }
1356 1396
1357 void P2PTransportChannel::OnReadyToSend(Connection* connection) { 1397 void P2PTransportChannel::OnReadyToSend(Connection* connection) {
1358 if (connection == best_connection_ && writable()) { 1398 if (connection == best_connection_ && writable()) {
1359 SignalReadyToSend(this); 1399 SignalReadyToSend(this);
1360 } 1400 }
1361 } 1401 }
1362 1402
1363 } // namespace cricket 1403 } // namespace cricket
OLDNEW
« no previous file with comments | « webrtc/p2p/base/p2ptransportchannel.h ('k') | webrtc/p2p/base/p2ptransportchannel_unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698