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

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, 1 month ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
1 /* 1 /*
2 * Copyright 2004 The WebRTC Project Authors. All rights reserved. 2 * Copyright 2004 The WebRTC Project Authors. All rights reserved.
3 * 3 *
4 * Use of this source code is governed by a BSD-style license 4 * Use of this source code is governed by a BSD-style license
5 * that can be found in the LICENSE file in the root of the source 5 * that can be found in the LICENSE file in the root of the source
6 * tree. An additional intellectual property rights grant can be found 6 * tree. An additional intellectual property rights grant can be found
7 * in the file PATENTS. All contributing project authors may 7 * in the file PATENTS. All contributing project authors may
8 * be found in the AUTHORS file in the root of the source tree. 8 * be found in the AUTHORS file in the root of the source tree.
9 */ 9 */
10 10
(...skipping 183 matching lines...) Expand 10 before | Expand all | Expand 10 after
194 // writable or not receiving. 194 // writable or not receiving.
195 const uint32_t WEAK_PING_DELAY = 1000 * PING_PACKET_SIZE / 10000; 195 const uint32_t WEAK_PING_DELAY = 1000 * PING_PACKET_SIZE / 10000;
196 196
197 // If the current best connection is both writable and receiving, then we will 197 // 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 198 // also try hard to make sure it is pinged at this rate (a little less than
199 // 2 * STRONG_PING_DELAY). 199 // 2 * STRONG_PING_DELAY).
200 static const uint32_t MAX_CURRENT_STRONG_DELAY = 900; 200 static const uint32_t MAX_CURRENT_STRONG_DELAY = 900;
201 201
202 static const int MIN_CHECK_RECEIVING_DELAY = 50; // ms 202 static const int MIN_CHECK_RECEIVING_DELAY = 50; // ms
203 203
204 // This is 5 seconds shorter than DEAD_CONNECTION_RECEIVE_TIMEOUT in port.h,
205 // so there are 5 seconds to retry pinging the backup connection before it
206 // becomes dead.
207 static const int BACKUP_CONNECTION_PING_INTERVAL = 25000; // ms
204 208
205 P2PTransportChannel::P2PTransportChannel(const std::string& transport_name, 209 P2PTransportChannel::P2PTransportChannel(const std::string& transport_name,
206 int component, 210 int component,
207 P2PTransport* transport, 211 P2PTransport* transport,
208 PortAllocator* allocator) 212 PortAllocator* allocator)
209 : TransportChannelImpl(transport_name, component), 213 : TransportChannelImpl(transport_name, component),
210 transport_(transport), 214 transport_(transport),
211 allocator_(allocator), 215 allocator_(allocator),
212 worker_thread_(rtc::Thread::Current()), 216 worker_thread_(rtc::Thread::Current()),
213 incoming_only_(false), 217 incoming_only_(false),
214 error_(0), 218 error_(0),
215 best_connection_(NULL), 219 best_connection_(NULL),
216 pending_best_connection_(NULL), 220 pending_best_connection_(NULL),
217 sort_dirty_(false), 221 sort_dirty_(false),
218 remote_ice_mode_(ICEMODE_FULL), 222 remote_ice_mode_(ICEMODE_FULL),
219 ice_role_(ICEROLE_UNKNOWN), 223 ice_role_(ICEROLE_UNKNOWN),
220 tiebreaker_(0), 224 tiebreaker_(0),
221 remote_candidate_generation_(0), 225 remote_candidate_generation_(0),
222 gathering_state_(kIceGatheringNew), 226 gathering_state_(kIceGatheringNew),
223 check_receiving_delay_(MIN_CHECK_RECEIVING_DELAY * 5), 227 check_receiving_delay_(MIN_CHECK_RECEIVING_DELAY * 5),
224 receiving_timeout_(MIN_CHECK_RECEIVING_DELAY * 50) { 228 receiving_timeout_(MIN_CHECK_RECEIVING_DELAY * 50),
229 backup_connection_ping_interval_(BACKUP_CONNECTION_PING_INTERVAL) {
pthatcher1 2015/11/20 05:34:38 We call one "delay" and the other "interval". It
honghaiz3 2015/11/20 20:10:06 I agree that the interval sounds better. I will ch
225 uint32_t weak_ping_delay = ::strtoul( 230 uint32_t weak_ping_delay = ::strtoul(
226 webrtc::field_trial::FindFullName("WebRTC-StunInterPacketDelay").c_str(), 231 webrtc::field_trial::FindFullName("WebRTC-StunInterPacketDelay").c_str(),
227 nullptr, 10); 232 nullptr, 10);
228 if (weak_ping_delay) { 233 if (weak_ping_delay) {
229 weak_ping_delay_ = weak_ping_delay; 234 weak_ping_delay_ = weak_ping_delay;
230 } 235 }
231 } 236 }
232 237
233 P2PTransportChannel::~P2PTransportChannel() { 238 P2PTransportChannel::~P2PTransportChannel() {
234 ASSERT(worker_thread_ == rtc::Thread::Current()); 239 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()); 294 ASSERT(worker_thread_ == rtc::Thread::Current());
290 if (!ports_.empty()) { 295 if (!ports_.empty()) {
291 LOG(LS_ERROR) 296 LOG(LS_ERROR)
292 << "Attempt to change tiebreaker after Port has been allocated."; 297 << "Attempt to change tiebreaker after Port has been allocated.";
293 return; 298 return;
294 } 299 }
295 300
296 tiebreaker_ = tiebreaker; 301 tiebreaker_ = tiebreaker;
297 } 302 }
298 303
304 TransportChannelState P2PTransportChannel::GetState() const {
305 return channel_state_;
pthatcher1 2015/11/20 05:34:37 Why not just state_?
honghaiz3 2015/11/20 20:10:06 Done.
306 }
307
299 // A channel is considered ICE completed once there is at most one active 308 // A channel is considered ICE completed once there is at most one active
300 // connection per network and at least one active connection. 309 // connection per network and at least one active connection.
301 TransportChannelState P2PTransportChannel::GetState() const { 310 TransportChannelState P2PTransportChannel::GetStateInternal() const {
302 if (!had_connection_) { 311 if (!had_connection_) {
303 return TransportChannelState::STATE_INIT; 312 return TransportChannelState::STATE_INIT;
304 } 313 }
305 314
306 std::vector<Connection*> active_connections; 315 std::vector<Connection*> active_connections;
307 for (Connection* connection : connections_) { 316 for (Connection* connection : connections_) {
308 if (connection->active()) { 317 if (connection->active()) {
309 active_connections.push_back(connection); 318 active_connections.push_back(connection);
310 } 319 }
311 } 320 }
(...skipping 53 matching lines...) Expand 10 before | Expand all | Expand 10 after
365 } 374 }
366 375
367 void P2PTransportChannel::SetRemoteIceMode(IceMode mode) { 376 void P2PTransportChannel::SetRemoteIceMode(IceMode mode) {
368 remote_ice_mode_ = mode; 377 remote_ice_mode_ = mode;
369 } 378 }
370 379
371 void P2PTransportChannel::SetIceConfig(const IceConfig& config) { 380 void P2PTransportChannel::SetIceConfig(const IceConfig& config) {
372 gather_continually_ = config.gather_continually; 381 gather_continually_ = config.gather_continually;
373 LOG(LS_INFO) << "Set gather_continually to " << gather_continually_; 382 LOG(LS_INFO) << "Set gather_continually to " << gather_continually_;
374 383
375 if (config.receiving_timeout_ms < 0) { 384 if (config.backup_connection_ping_interval >= 0) {
376 return; 385 backup_connection_ping_interval_ = config.backup_connection_ping_interval;
386 LOG(LS_INFO) << "Set backup connection ping interval to "
387 << backup_connection_ping_interval_ << " milliseconds.";
pthatcher1 2015/11/20 05:34:37 You probably only want to log this it if it change
honghaiz3 2015/11/20 20:10:06 Done. Only set and log this if the value changes.
377 } 388 }
378 receiving_timeout_ = config.receiving_timeout_ms;
379 check_receiving_delay_ =
380 std::max(MIN_CHECK_RECEIVING_DELAY, receiving_timeout_ / 10);
381 389
382 for (Connection* connection : connections_) { 390 if (config.receiving_timeout_ms >= 0) {
383 connection->set_receiving_timeout(receiving_timeout_); 391 receiving_timeout_ = config.receiving_timeout_ms;
392 check_receiving_delay_ =
393 std::max(MIN_CHECK_RECEIVING_DELAY, receiving_timeout_ / 10);
394
395 for (Connection* connection : connections_) {
396 connection->set_receiving_timeout(receiving_timeout_);
397 }
398 LOG(LS_INFO) << "Set ICE receiving timeout to " << receiving_timeout_
399 << " milliseconds";
pthatcher1 2015/11/20 05:34:38 Same here.
honghaiz3 2015/11/20 20:10:06 Done.
384 } 400 }
385 LOG(LS_INFO) << "Set ICE receiving timeout to " << receiving_timeout_
386 << " milliseconds";
387 } 401 }
388 402
389 // Go into the state of processing candidates, and running in general 403 // Go into the state of processing candidates, and running in general
390 void P2PTransportChannel::Connect() { 404 void P2PTransportChannel::Connect() {
391 ASSERT(worker_thread_ == rtc::Thread::Current()); 405 ASSERT(worker_thread_ == rtc::Thread::Current());
392 if (ice_ufrag_.empty() || ice_pwd_.empty()) { 406 if (ice_ufrag_.empty() || ice_pwd_.empty()) {
393 ASSERT(false); 407 ASSERT(false);
394 LOG(LS_ERROR) << "P2PTransportChannel::Connect: The ice_ufrag_ and the " 408 LOG(LS_ERROR) << "P2PTransportChannel::Connect: The ice_ufrag_ and the "
395 << "ice_pwd_ are not set."; 409 << "ice_pwd_ are not set.";
396 return; 410 return;
(...skipping 647 matching lines...) Expand 10 before | Expand all | Expand 10 after
1044 } 1058 }
1045 LOG_J(LS_INFO, this) << "New best connection: " 1059 LOG_J(LS_INFO, this) << "New best connection: "
1046 << best_connection_->ToString(); 1060 << best_connection_->ToString();
1047 SignalRouteChange(this, best_connection_->remote_candidate()); 1061 SignalRouteChange(this, best_connection_->remote_candidate());
1048 } else { 1062 } else {
1049 LOG_J(LS_INFO, this) << "No best connection"; 1063 LOG_J(LS_INFO, this) << "No best connection";
1050 } 1064 }
1051 } 1065 }
1052 1066
1053 void P2PTransportChannel::UpdateChannelState() { 1067 void P2PTransportChannel::UpdateChannelState() {
1068 channel_state_ = GetStateInternal();
pthatcher1 2015/11/20 05:34:37 So what's the advantage of cacheing the state and
honghaiz3 2015/11/20 20:10:06 Basically I want to avoid too much unnecessary com
1069
1054 bool writable = best_connection_ && best_connection_->writable(); 1070 bool writable = best_connection_ && best_connection_->writable();
1055 set_writable(writable); 1071 set_writable(writable);
1056 1072
1057 bool receiving = false; 1073 bool receiving = false;
1058 for (const Connection* connection : connections_) { 1074 for (const Connection* connection : connections_) {
1059 if (connection->receiving()) { 1075 if (connection->receiving()) {
1060 receiving = true; 1076 receiving = true;
1061 break; 1077 break;
1062 } 1078 }
1063 } 1079 }
(...skipping 82 matching lines...) Expand 10 before | Expand all | Expand 10 after
1146 PingConnection(conn); 1162 PingConnection(conn);
1147 } 1163 }
1148 } 1164 }
1149 int check_delay = std::min(ping_delay, check_receiving_delay_); 1165 int check_delay = std::min(ping_delay, check_receiving_delay_);
1150 thread()->PostDelayed(check_delay, this, MSG_CHECK_AND_PING); 1166 thread()->PostDelayed(check_delay, this, MSG_CHECK_AND_PING);
1151 } 1167 }
1152 1168
1153 // Is the connection in a state for us to even consider pinging the other side? 1169 // 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 1170 // 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. 1171 // how a TCP connection is kicked into reconnecting on the active side.
1156 bool P2PTransportChannel::IsPingable(Connection* conn) { 1172 bool P2PTransportChannel::IsPingable(Connection* conn, uint32_t now) {
1157 const Candidate& remote = conn->remote_candidate(); 1173 const Candidate& remote = conn->remote_candidate();
1158 // We should never get this far with an empty remote ufrag. 1174 // We should never get this far with an empty remote ufrag.
1159 ASSERT(!remote.username().empty()); 1175 ASSERT(!remote.username().empty());
1160 if (remote.username().empty() || remote.password().empty()) { 1176 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. 1177 // If we don't have an ICE ufrag and pwd, there's no way we can ping.
1162 return false; 1178 return false;
1163 } 1179 }
1164 1180
1165 // An never connected connection cannot be written to at all, so pinging is 1181 // 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 1182 // out of the question. However, if it has become WRITABLE, it is in the
1167 // reconnecting state so ping is needed. 1183 // reconnecting state so ping is needed.
1168 if (!conn->connected() && !conn->writable()) { 1184 if (!conn->connected() && !conn->writable()) {
1169 return false; 1185 return false;
1170 } 1186 }
1171 1187
1172 // If the channel is weak, ping all candidates. Otherwise, we only 1188 // If the channel is weakly connected, ping all connections.
1173 // want to ping connections that have not timed out on writing. 1189 if (weak()) {
1174 return weak() || conn->write_state() != Connection::STATE_WRITE_TIMEOUT; 1190 return true;
1191 }
1192
1193 // If the channel is not COMPLETED,
pthatcher1 2015/11/20 05:34:37 Might be more readable as "If the channel is stron
honghaiz3 2015/11/20 20:10:06 Done.
1194 // ping connections that have not timed out on writing.
pthatcher1 2015/11/20 05:34:38 To match the code, you should say "ping all active
honghaiz3 2015/11/20 20:10:06 Done.
1195 if (channel_state_ != STATE_COMPLETED) {
1196 return conn->active();
1197 }
1198 // If the channel is strongly connected and it is COMPLETED, ping the backup
1199 // connection once every |backup_connection_ping_interval_| milliseconds.
pthatcher1 2015/11/20 05:34:38 The comment says "ping the backup connection", but
honghaiz3 2015/11/20 20:10:06 Thanks. made a small change, requiring that backup
1200 return conn == best_connection_ ||
1201 now >= (conn->last_ping_response_received() +
1202 backup_connection_ping_interval_);
1175 } 1203 }
1176 1204
1177 // Returns the next pingable connection to ping. This will be the oldest 1205 // Returns the next pingable connection to ping. This will be the oldest
1178 // pingable connection unless we have a connected, writable connection that is 1206 // pingable connection unless we have a connected, writable connection that is
1179 // past the maximum acceptable ping delay. When reconnecting a TCP connection, 1207 // past the maximum acceptable ping delay. When reconnecting a TCP connection,
1180 // the best connection is disconnected, although still WRITABLE while 1208 // the best connection is disconnected, although still WRITABLE while
1181 // reconnecting. The newly created connection should be selected as the ping 1209 // reconnecting. The newly created connection should be selected as the ping
1182 // target to become writable instead. See the big comment in CompareConnections. 1210 // target to become writable instead. See the big comment in CompareConnections.
1183 Connection* P2PTransportChannel::FindNextPingableConnection() { 1211 Connection* P2PTransportChannel::FindNextPingableConnection() {
1184 uint32_t now = rtc::Time(); 1212 uint32_t now = rtc::Time();
1185 if (best_connection_ && best_connection_->connected() && 1213 if (best_connection_ && best_connection_->connected() &&
1186 best_connection_->writable() && 1214 best_connection_->writable() &&
1187 (best_connection_->last_ping_sent() + MAX_CURRENT_STRONG_DELAY <= now)) { 1215 (best_connection_->last_ping_sent() + MAX_CURRENT_STRONG_DELAY <= now)) {
1188 return best_connection_; 1216 return best_connection_;
1189 } 1217 }
1190 1218
1191 // First, find "triggered checks". We ping first those connections 1219 // First, find "triggered checks". We ping first those connections
1192 // that have received a ping but have not sent a ping since receiving 1220 // 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 1221 // it (last_received_ping > last_sent_ping). But we shouldn't do
1194 // triggered checks if the connection is already writable. 1222 // triggered checks if the connection is already writable.
1195 Connection* oldest_needing_triggered_check = nullptr; 1223 Connection* oldest_needing_triggered_check = nullptr;
1196 Connection* oldest = nullptr; 1224 Connection* oldest = nullptr;
1197 for (Connection* conn : connections_) { 1225 for (Connection* conn : connections_) {
1198 if (!IsPingable(conn)) { 1226 if (!IsPingable(conn, now)) {
1199 continue; 1227 continue;
1200 } 1228 }
1201 bool needs_triggered_check = 1229 bool needs_triggered_check =
1202 (!conn->writable() && 1230 (!conn->writable() &&
1203 conn->last_ping_received() > conn->last_ping_sent()); 1231 conn->last_ping_received() > conn->last_ping_sent());
1204 if (needs_triggered_check && 1232 if (needs_triggered_check &&
1205 (!oldest_needing_triggered_check || 1233 (!oldest_needing_triggered_check ||
1206 (conn->last_ping_received() < 1234 (conn->last_ping_received() <
1207 oldest_needing_triggered_check->last_ping_received()))) { 1235 oldest_needing_triggered_check->last_ping_received()))) {
1208 oldest_needing_triggered_check = conn; 1236 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 1328 // 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. 1329 // 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 1330 // 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. 1331 // and re-choose a best assuming that there was no best connection.
1304 if (best_connection_ == connection) { 1332 if (best_connection_ == connection) {
1305 LOG(LS_INFO) << "Best connection destroyed. Will choose a new one."; 1333 LOG(LS_INFO) << "Best connection destroyed. Will choose a new one.";
1306 SwitchBestConnectionTo(NULL); 1334 SwitchBestConnectionTo(NULL);
1307 RequestSort(); 1335 RequestSort();
1308 } 1336 }
1309 1337
1338 UpdateChannelState();
pthatcher1 2015/11/20 05:34:38 This kind of thing makes me worry that we won't re
honghaiz3 2015/11/20 20:10:06 I am pretty sure this is the only place we need to
1339
1310 SignalConnectionRemoved(this); 1340 SignalConnectionRemoved(this);
1311 } 1341 }
1312 1342
1313 // When a port is destroyed remove it from our list of ports to use for 1343 // When a port is destroyed remove it from our list of ports to use for
1314 // connection attempts. 1344 // connection attempts.
1315 void P2PTransportChannel::OnPortDestroyed(PortInterface* port) { 1345 void P2PTransportChannel::OnPortDestroyed(PortInterface* port) {
1316 ASSERT(worker_thread_ == rtc::Thread::Current()); 1346 ASSERT(worker_thread_ == rtc::Thread::Current());
1317 1347
1318 // Remove this port from the list (if we didn't drop it already). 1348 // Remove this port from the list (if we didn't drop it already).
1319 std::vector<PortInterface*>::iterator iter = 1349 std::vector<PortInterface*>::iterator iter =
(...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after
1354 SignalSentPacket(this, sent_packet); 1384 SignalSentPacket(this, sent_packet);
1355 } 1385 }
1356 1386
1357 void P2PTransportChannel::OnReadyToSend(Connection* connection) { 1387 void P2PTransportChannel::OnReadyToSend(Connection* connection) {
1358 if (connection == best_connection_ && writable()) { 1388 if (connection == best_connection_ && writable()) {
1359 SignalReadyToSend(this); 1389 SignalReadyToSend(this);
1360 } 1390 }
1361 } 1391 }
1362 1392
1363 } // namespace cricket 1393 } // namespace cricket
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698