OLD | NEW |
---|---|
1 /* | 1 /* |
2 * Copyright 2004 The WebRTC Project Authors. All rights reserved. | 2 * Copyright 2004 The WebRTC Project Authors. All rights reserved. |
3 * | 3 * |
4 * Use of this source code is governed by a BSD-style license | 4 * Use of this source code is governed by a BSD-style license |
5 * that can be found in the LICENSE file in the root of the source | 5 * that can be found in the LICENSE file in the root of the source |
6 * tree. An additional intellectual property rights grant can be found | 6 * tree. An additional intellectual property rights grant can be found |
7 * in the file PATENTS. All contributing project authors may | 7 * in the file PATENTS. All contributing project authors may |
8 * be found in the AUTHORS file in the root of the source tree. | 8 * be found in the AUTHORS file in the root of the source tree. |
9 */ | 9 */ |
10 | 10 |
(...skipping 183 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
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 Loading... | |
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 Loading... | |
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 Loading... | |
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 Loading... | |
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 Loading... | |
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 Loading... | |
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 |
OLD | NEW |