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 169 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
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 Loading... | |
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 { | |
pthatcher1
2015/12/01 19:40:25
Can we just change this to state()?
honghaiz3
2015/12/01 23:43:08
This is a virtual method.
| |
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 Loading... | |
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 647 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
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 void P2PTransportChannel::UpdateChannelState() { |
1067 state_ = ComputeState(); | |
pthatcher1
2015/12/01 19:40:25
Since ComputeState is never called anywhere else,
honghaiz3
2015/12/01 23:43:08
Changed to UpdateState
ComputeState has a lot of e
| |
1068 | |
1054 bool writable = best_connection_ && best_connection_->writable(); | 1069 bool writable = best_connection_ && best_connection_->writable(); |
1055 set_writable(writable); | 1070 set_writable(writable); |
1056 | 1071 |
1057 bool receiving = false; | 1072 bool receiving = false; |
1058 for (const Connection* connection : connections_) { | 1073 for (const Connection* connection : connections_) { |
1059 if (connection->receiving()) { | 1074 if (connection->receiving()) { |
1060 receiving = true; | 1075 receiving = true; |
1061 break; | 1076 break; |
1062 } | 1077 } |
1063 } | 1078 } |
(...skipping 79 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1143 if (rtc::Time() >= last_ping_sent_ms_ + ping_delay) { | 1158 if (rtc::Time() >= last_ping_sent_ms_ + ping_delay) { |
1144 Connection* conn = FindNextPingableConnection(); | 1159 Connection* conn = FindNextPingableConnection(); |
1145 if (conn) { | 1160 if (conn) { |
1146 PingConnection(conn); | 1161 PingConnection(conn); |
1147 } | 1162 } |
1148 } | 1163 } |
1149 int check_delay = std::min(ping_delay, check_receiving_delay_); | 1164 int check_delay = std::min(ping_delay, check_receiving_delay_); |
1150 thread()->PostDelayed(check_delay, this, MSG_CHECK_AND_PING); | 1165 thread()->PostDelayed(check_delay, this, MSG_CHECK_AND_PING); |
1151 } | 1166 } |
1152 | 1167 |
1168 // A connection is considered a backup connection if the channel state | |
1169 // is complete, the connection is not the best connection and it is active. | |
pthatcher1
2015/12/01 19:40:25
complete => completed
honghaiz3
2015/12/01 23:43:08
Done.
| |
1170 bool P2PTransportChannel::IsBackupConnection(Connection* conn) const { | |
1171 return state_ == STATE_COMPLETED && conn != best_connection_ && | |
1172 conn->active(); | |
1173 } | |
1174 | |
1153 // Is the connection in a state for us to even consider pinging the other side? | 1175 // 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 | 1176 // 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. | 1177 // how a TCP connection is kicked into reconnecting on the active side. |
1156 bool P2PTransportChannel::IsPingable(Connection* conn) { | 1178 bool P2PTransportChannel::IsPingable(Connection* conn, uint32_t now) { |
1157 const Candidate& remote = conn->remote_candidate(); | 1179 const Candidate& remote = conn->remote_candidate(); |
1158 // We should never get this far with an empty remote ufrag. | 1180 // We should never get this far with an empty remote ufrag. |
1159 ASSERT(!remote.username().empty()); | 1181 ASSERT(!remote.username().empty()); |
1160 if (remote.username().empty() || remote.password().empty()) { | 1182 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. | 1183 // If we don't have an ICE ufrag and pwd, there's no way we can ping. |
1162 return false; | 1184 return false; |
1163 } | 1185 } |
1164 | 1186 |
1165 // An never connected connection cannot be written to at all, so pinging is | 1187 // 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 | 1188 // out of the question. However, if it has become WRITABLE, it is in the |
1167 // reconnecting state so ping is needed. | 1189 // reconnecting state so ping is needed. |
1168 if (!conn->connected() && !conn->writable()) { | 1190 if (!conn->connected() && !conn->writable()) { |
1169 return false; | 1191 return false; |
1170 } | 1192 } |
1171 | 1193 |
1172 // If the channel is weak, ping all candidates. Otherwise, we only | 1194 // If the channel is weakly connected, ping all connections. |
1173 // want to ping connections that have not timed out on writing. | 1195 if (weak()) { |
1174 return weak() || conn->write_state() != Connection::STATE_WRITE_TIMEOUT; | 1196 return true; |
1197 } | |
1198 | |
1199 // Always ping active connections regardless whether the channel is completed | |
1200 // or not, but backup connections are pinged at a slower rate. | |
1201 if (IsBackupConnection(conn)) { | |
1202 return (now >= conn->last_ping_response_received() + | |
1203 backup_connection_ping_interval_); | |
1204 } | |
1205 return conn->active(); | |
1175 } | 1206 } |
1176 | 1207 |
1177 // Returns the next pingable connection to ping. This will be the oldest | 1208 // Returns the next pingable connection to ping. This will be the oldest |
1178 // pingable connection unless we have a connected, writable connection that is | 1209 // pingable connection unless we have a connected, writable connection that is |
1179 // past the maximum acceptable ping delay. When reconnecting a TCP connection, | 1210 // past the maximum acceptable ping delay. When reconnecting a TCP connection, |
1180 // the best connection is disconnected, although still WRITABLE while | 1211 // the best connection is disconnected, although still WRITABLE while |
1181 // reconnecting. The newly created connection should be selected as the ping | 1212 // reconnecting. The newly created connection should be selected as the ping |
1182 // target to become writable instead. See the big comment in CompareConnections. | 1213 // target to become writable instead. See the big comment in CompareConnections. |
1183 Connection* P2PTransportChannel::FindNextPingableConnection() { | 1214 Connection* P2PTransportChannel::FindNextPingableConnection() { |
1184 uint32_t now = rtc::Time(); | 1215 uint32_t now = rtc::Time(); |
1185 if (best_connection_ && best_connection_->connected() && | 1216 if (best_connection_ && best_connection_->connected() && |
1186 best_connection_->writable() && | 1217 best_connection_->writable() && |
1187 (best_connection_->last_ping_sent() + MAX_CURRENT_STRONG_DELAY <= now)) { | 1218 (best_connection_->last_ping_sent() + MAX_CURRENT_STRONG_DELAY <= now)) { |
1188 return best_connection_; | 1219 return best_connection_; |
1189 } | 1220 } |
1190 | 1221 |
1191 // First, find "triggered checks". We ping first those connections | 1222 // First, find "triggered checks". We ping first those connections |
1192 // that have received a ping but have not sent a ping since receiving | 1223 // 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 | 1224 // it (last_received_ping > last_sent_ping). But we shouldn't do |
1194 // triggered checks if the connection is already writable. | 1225 // triggered checks if the connection is already writable. |
1195 Connection* oldest_needing_triggered_check = nullptr; | 1226 Connection* oldest_needing_triggered_check = nullptr; |
1196 Connection* oldest = nullptr; | 1227 Connection* oldest = nullptr; |
1197 for (Connection* conn : connections_) { | 1228 for (Connection* conn : connections_) { |
1198 if (!IsPingable(conn)) { | 1229 if (!IsPingable(conn, now)) { |
1199 continue; | 1230 continue; |
1200 } | 1231 } |
1201 bool needs_triggered_check = | 1232 bool needs_triggered_check = |
1202 (!conn->writable() && | 1233 (!conn->writable() && |
1203 conn->last_ping_received() > conn->last_ping_sent()); | 1234 conn->last_ping_received() > conn->last_ping_sent()); |
1204 if (needs_triggered_check && | 1235 if (needs_triggered_check && |
1205 (!oldest_needing_triggered_check || | 1236 (!oldest_needing_triggered_check || |
1206 (conn->last_ping_received() < | 1237 (conn->last_ping_received() < |
1207 oldest_needing_triggered_check->last_ping_received()))) { | 1238 oldest_needing_triggered_check->last_ping_received()))) { |
1208 oldest_needing_triggered_check = conn; | 1239 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 | 1331 // 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. | 1332 // 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 | 1333 // 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. | 1334 // and re-choose a best assuming that there was no best connection. |
1304 if (best_connection_ == connection) { | 1335 if (best_connection_ == connection) { |
1305 LOG(LS_INFO) << "Best connection destroyed. Will choose a new one."; | 1336 LOG(LS_INFO) << "Best connection destroyed. Will choose a new one."; |
1306 SwitchBestConnectionTo(NULL); | 1337 SwitchBestConnectionTo(NULL); |
1307 RequestSort(); | 1338 RequestSort(); |
1308 } | 1339 } |
1309 | 1340 |
1341 UpdateChannelState(); | |
1342 // SignalConnectionRemoved should be called after the channel state is | |
1343 // updated because the receiver of the event may access the channel state. | |
1310 SignalConnectionRemoved(this); | 1344 SignalConnectionRemoved(this); |
1311 } | 1345 } |
1312 | 1346 |
1313 // When a port is destroyed remove it from our list of ports to use for | 1347 // When a port is destroyed remove it from our list of ports to use for |
1314 // connection attempts. | 1348 // connection attempts. |
1315 void P2PTransportChannel::OnPortDestroyed(PortInterface* port) { | 1349 void P2PTransportChannel::OnPortDestroyed(PortInterface* port) { |
1316 ASSERT(worker_thread_ == rtc::Thread::Current()); | 1350 ASSERT(worker_thread_ == rtc::Thread::Current()); |
1317 | 1351 |
1318 // Remove this port from the list (if we didn't drop it already). | 1352 // Remove this port from the list (if we didn't drop it already). |
1319 std::vector<PortInterface*>::iterator iter = | 1353 std::vector<PortInterface*>::iterator iter = |
(...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1354 SignalSentPacket(this, sent_packet); | 1388 SignalSentPacket(this, sent_packet); |
1355 } | 1389 } |
1356 | 1390 |
1357 void P2PTransportChannel::OnReadyToSend(Connection* connection) { | 1391 void P2PTransportChannel::OnReadyToSend(Connection* connection) { |
1358 if (connection == best_connection_ && writable()) { | 1392 if (connection == best_connection_ && writable()) { |
1359 SignalReadyToSend(this); | 1393 SignalReadyToSend(this); |
1360 } | 1394 } |
1361 } | 1395 } |
1362 | 1396 |
1363 } // namespace cricket | 1397 } // namespace cricket |
OLD | NEW |