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 180 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
191 // 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 |
192 // writable and receiving. | 192 // writable and receiving. |
193 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; |
194 // 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 |
195 // writable or not receiving. | 195 // writable or not receiving. |
196 const uint32_t WEAK_PING_DELAY = 1000 * PING_PACKET_SIZE / 10000; | 196 const uint32_t WEAK_PING_DELAY = 1000 * PING_PACKET_SIZE / 10000; |
197 | 197 |
198 // 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 |
199 // 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 |
200 // 2 * STRONG_PING_DELAY). | 200 // 2 * STRONG_PING_DELAY). |
201 static const uint32_t MAX_CURRENT_STRONG_DELAY = 900; | 201 const uint32_t MAX_CURRENT_STRONG_DELAY = 900; |
202 | 202 |
203 static const int MIN_CHECK_RECEIVING_DELAY = 50; // ms | 203 static const int MIN_CHECK_RECEIVING_DELAY = 50; // ms |
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 connections_(this), | |
215 best_connection_(NULL), | 216 best_connection_(NULL), |
216 pending_best_connection_(NULL), | 217 pending_best_connection_(NULL), |
217 sort_dirty_(false), | 218 sort_dirty_(false), |
218 remote_ice_mode_(ICEMODE_FULL), | 219 remote_ice_mode_(ICEMODE_FULL), |
219 ice_role_(ICEROLE_UNKNOWN), | 220 ice_role_(ICEROLE_UNKNOWN), |
220 tiebreaker_(0), | 221 tiebreaker_(0), |
221 gathering_state_(kIceGatheringNew), | 222 gathering_state_(kIceGatheringNew), |
222 check_receiving_delay_(MIN_CHECK_RECEIVING_DELAY * 5), | 223 check_receiving_delay_(MIN_CHECK_RECEIVING_DELAY * 5), |
223 receiving_timeout_(MIN_CHECK_RECEIVING_DELAY * 50), | 224 receiving_timeout_(MIN_CHECK_RECEIVING_DELAY * 50), |
224 backup_connection_ping_interval_(0) { | 225 backup_connection_ping_interval_(0) { |
(...skipping 162 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
387 receiving_timeout_ = config.receiving_timeout_ms; | 388 receiving_timeout_ = config.receiving_timeout_ms; |
388 check_receiving_delay_ = | 389 check_receiving_delay_ = |
389 std::max(MIN_CHECK_RECEIVING_DELAY, receiving_timeout_ / 10); | 390 std::max(MIN_CHECK_RECEIVING_DELAY, receiving_timeout_ / 10); |
390 | 391 |
391 for (Connection* connection : connections_) { | 392 for (Connection* connection : connections_) { |
392 connection->set_receiving_timeout(receiving_timeout_); | 393 connection->set_receiving_timeout(receiving_timeout_); |
393 } | 394 } |
394 LOG(LS_INFO) << "Set ICE receiving timeout to " << receiving_timeout_ | 395 LOG(LS_INFO) << "Set ICE receiving timeout to " << receiving_timeout_ |
395 << " milliseconds"; | 396 << " milliseconds"; |
396 } | 397 } |
398 | |
399 connections_.enable_most_likely_first( | |
400 config.ping_most_likely_candidate_pair_first); | |
401 LOG(LS_INFO) << "Set ping most likely connection to " | |
402 << connections_.most_likely_first(); | |
pthatcher1
2016/01/27 19:59:58
This might be better named prioritize_most_likely_
guoweis_webrtc
2016/02/29 18:03:00
Done.
| |
403 } | |
404 | |
405 IceConfig P2PTransportChannel::GetIceConfig() const { | |
406 IceConfig config; | |
407 config.gather_continually = gather_continually_; | |
408 config.receiving_timeout_ms = receiving_timeout_; | |
409 config.ping_most_likely_candidate_pair_first = | |
410 connections_.most_likely_first(); | |
411 return config; | |
pthatcher1
2016/01/27 19:59:58
Instead of converting between the struct and the m
guoweis_webrtc
2016/02/29 18:03:00
Done.
| |
397 } | 412 } |
398 | 413 |
399 // Go into the state of processing candidates, and running in general | 414 // Go into the state of processing candidates, and running in general |
400 void P2PTransportChannel::Connect() { | 415 void P2PTransportChannel::Connect() { |
401 ASSERT(worker_thread_ == rtc::Thread::Current()); | 416 ASSERT(worker_thread_ == rtc::Thread::Current()); |
402 if (ice_ufrag_.empty() || ice_pwd_.empty()) { | 417 if (ice_ufrag_.empty() || ice_pwd_.empty()) { |
403 ASSERT(false); | 418 ASSERT(false); |
404 LOG(LS_ERROR) << "P2PTransportChannel::Connect: The ice_ufrag_ and the " | 419 LOG(LS_ERROR) << "P2PTransportChannel::Connect: The ice_ufrag_ and the " |
405 << "ice_pwd_ are not set."; | 420 << "ice_pwd_ are not set."; |
406 return; | 421 return; |
(...skipping 194 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
601 return; | 616 return; |
602 } else { | 617 } else { |
603 ASSERT(false); | 618 ASSERT(false); |
604 port->SendBindingErrorResponse(stun_msg, address, | 619 port->SendBindingErrorResponse(stun_msg, address, |
605 STUN_ERROR_SERVER_ERROR, | 620 STUN_ERROR_SERVER_ERROR, |
606 STUN_ERROR_REASON_SERVER_ERROR); | 621 STUN_ERROR_REASON_SERVER_ERROR); |
607 return; | 622 return; |
608 } | 623 } |
609 } | 624 } |
610 | 625 |
611 Connection* connection = port->CreateConnection( | 626 Connection* connection = |
612 remote_candidate, cricket::PortInterface::ORIGIN_THIS_PORT); | 627 port->CreateConnection(remote_candidate, PortInterface::ORIGIN_THIS_PORT); |
613 if (!connection) { | 628 if (!connection) { |
614 ASSERT(false); | 629 ASSERT(false); |
615 port->SendBindingErrorResponse(stun_msg, address, STUN_ERROR_SERVER_ERROR, | 630 port->SendBindingErrorResponse(stun_msg, address, STUN_ERROR_SERVER_ERROR, |
616 STUN_ERROR_REASON_SERVER_ERROR); | 631 STUN_ERROR_REASON_SERVER_ERROR); |
617 return; | 632 return; |
618 } | 633 } |
619 | 634 |
620 LOG(LS_INFO) << "Adding connection from " | 635 LOG(LS_INFO) << "Adding connection from " |
621 << (remote_candidate_is_new ? "peer reflexive" : "resurrected") | 636 << (remote_candidate_is_new ? "peer reflexive" : "resurrected") |
622 << " candidate: " << remote_candidate.ToString(); | 637 << " candidate: " << remote_candidate.ToString(); |
(...skipping 156 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
779 << connection->remote_candidate().ToString() | 794 << connection->remote_candidate().ToString() |
780 << "New remote candidate: " | 795 << "New remote candidate: " |
781 << remote_candidate.ToString(); | 796 << remote_candidate.ToString(); |
782 return false; | 797 return false; |
783 } | 798 } |
784 } else { | 799 } else { |
785 PortInterface::CandidateOrigin origin = GetOrigin(port, origin_port); | 800 PortInterface::CandidateOrigin origin = GetOrigin(port, origin_port); |
786 | 801 |
787 // Don't create connection if this is a candidate we received in a | 802 // Don't create connection if this is a candidate we received in a |
788 // message and we are not allowed to make outgoing connections. | 803 // message and we are not allowed to make outgoing connections. |
789 if (origin == cricket::PortInterface::ORIGIN_MESSAGE && incoming_only_) | 804 if (origin == PortInterface::ORIGIN_MESSAGE && incoming_only_) |
790 return false; | 805 return false; |
791 | 806 |
792 connection = port->CreateConnection(remote_candidate, origin); | 807 connection = port->CreateConnection(remote_candidate, origin); |
793 if (!connection) | 808 if (!connection) |
794 return false; | 809 return false; |
795 | 810 |
796 AddConnection(connection); | 811 AddConnection(connection); |
797 | 812 |
798 LOG_J(LS_INFO, this) << "Created connection with origin=" << origin << ", (" | 813 LOG_J(LS_INFO, this) << "Created connection with origin=" << origin << ", (" |
799 << connections_.size() << " total)"; | 814 << connections_.size() << " total)"; |
800 } | 815 } |
801 | 816 |
802 return true; | 817 return true; |
803 } | 818 } |
804 | 819 |
805 bool P2PTransportChannel::FindConnection( | 820 bool P2PTransportChannel::FindConnection(Connection* connection) const { |
806 cricket::Connection* connection) const { | |
807 std::vector<Connection*>::const_iterator citer = | 821 std::vector<Connection*>::const_iterator citer = |
808 std::find(connections_.begin(), connections_.end(), connection); | 822 std::find(connections_.begin(), connections_.end(), connection); |
809 return citer != connections_.end(); | 823 return citer != connections_.end(); |
810 } | 824 } |
811 | 825 |
812 uint32_t P2PTransportChannel::GetRemoteCandidateGeneration( | 826 uint32_t P2PTransportChannel::GetRemoteCandidateGeneration( |
813 const Candidate& candidate) { | 827 const Candidate& candidate) { |
814 // If the candidate has a ufrag, use it to find the generation. | 828 // If the candidate has a ufrag, use it to find the generation. |
815 if (!candidate.username().empty()) { | 829 if (!candidate.username().empty()) { |
816 uint32_t generation = 0; | 830 uint32_t generation = 0; |
(...skipping 431 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1248 return conn->active(); | 1262 return conn->active(); |
1249 } | 1263 } |
1250 | 1264 |
1251 // Returns the next pingable connection to ping. This will be the oldest | 1265 // Returns the next pingable connection to ping. This will be the oldest |
1252 // pingable connection unless we have a connected, writable connection that is | 1266 // pingable connection unless we have a connected, writable connection that is |
1253 // past the maximum acceptable ping delay. When reconnecting a TCP connection, | 1267 // past the maximum acceptable ping delay. When reconnecting a TCP connection, |
1254 // the best connection is disconnected, although still WRITABLE while | 1268 // the best connection is disconnected, although still WRITABLE while |
1255 // reconnecting. The newly created connection should be selected as the ping | 1269 // reconnecting. The newly created connection should be selected as the ping |
1256 // target to become writable instead. See the big comment in CompareConnections. | 1270 // target to become writable instead. See the big comment in CompareConnections. |
1257 Connection* P2PTransportChannel::FindNextPingableConnection() { | 1271 Connection* P2PTransportChannel::FindNextPingableConnection() { |
1272 if (connections_.empty()) { | |
1273 return nullptr; | |
1274 } | |
pthatcher1
2016/01/27 19:59:58
Why is this needed? Can't connection_ just handle
guoweis_webrtc
2016/02/29 18:03:00
Done.
| |
1275 | |
1258 uint32_t now = rtc::Time(); | 1276 uint32_t now = rtc::Time(); |
1259 if (best_connection_ && best_connection_->connected() && | 1277 if (best_connection_ && best_connection_->connected() && |
1260 best_connection_->writable() && | 1278 best_connection_->writable() && |
1261 (best_connection_->last_ping_sent() + MAX_CURRENT_STRONG_DELAY <= now)) { | 1279 (best_connection_->last_ping_sent() + MAX_CURRENT_STRONG_DELAY <= now)) { |
1280 connections_.MarkConnectionPinged(best_connection_); | |
pthatcher1
2016/01/27 19:59:58
I don't think FindNextPingableConnection should do
guoweis_webrtc
2016/02/29 18:03:00
Removed this function.
| |
1262 return best_connection_; | 1281 return best_connection_; |
1263 } | 1282 } |
1264 | 1283 |
1265 // First, find "triggered checks". We ping first those connections | 1284 return connections_.FindNextPingableConnection(now); |
1266 // that have received a ping but have not sent a ping since receiving | |
1267 // it (last_received_ping > last_sent_ping). But we shouldn't do | |
1268 // triggered checks if the connection is already writable. | |
1269 Connection* oldest_needing_triggered_check = nullptr; | |
1270 Connection* oldest = nullptr; | |
1271 for (Connection* conn : connections_) { | |
1272 if (!IsPingable(conn, now)) { | |
1273 continue; | |
1274 } | |
1275 bool needs_triggered_check = | |
1276 (!conn->writable() && | |
1277 conn->last_ping_received() > conn->last_ping_sent()); | |
1278 if (needs_triggered_check && | |
1279 (!oldest_needing_triggered_check || | |
1280 (conn->last_ping_received() < | |
1281 oldest_needing_triggered_check->last_ping_received()))) { | |
1282 oldest_needing_triggered_check = conn; | |
1283 } | |
1284 if (!oldest || (conn->last_ping_sent() < oldest->last_ping_sent())) { | |
1285 oldest = conn; | |
1286 } | |
1287 } | |
1288 | |
1289 if (oldest_needing_triggered_check) { | |
1290 LOG(LS_INFO) << "Selecting connection for triggered check: " << | |
1291 oldest_needing_triggered_check->ToString(); | |
1292 return oldest_needing_triggered_check; | |
1293 } | |
1294 return oldest; | |
1295 } | 1285 } |
1296 | 1286 |
1297 // Apart from sending ping from |conn| this method also updates | 1287 // Apart from sending ping from |conn| this method also updates |
1298 // |use_candidate_attr| flag. The criteria to update this flag is | 1288 // |use_candidate_attr| flag. The criteria to update this flag is |
1299 // explained below. | 1289 // explained below. |
1300 // Set USE-CANDIDATE if doing ICE AND this channel is in CONTROLLING AND | 1290 // Set USE-CANDIDATE if doing ICE AND this channel is in CONTROLLING AND |
1301 // a) Channel is in FULL ICE AND | 1291 // a) Channel is in FULL ICE AND |
1302 // a.1) |conn| is the best connection OR | 1292 // a.1) |conn| is the best connection OR |
1303 // a.2) there is no best connection OR | 1293 // a.2) there is no best connection OR |
1304 // a.3) the best connection is unwritable OR | 1294 // a.3) the best connection is unwritable OR |
(...skipping 125 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1430 | 1420 |
1431 SignalSentPacket(this, sent_packet); | 1421 SignalSentPacket(this, sent_packet); |
1432 } | 1422 } |
1433 | 1423 |
1434 void P2PTransportChannel::OnReadyToSend(Connection* connection) { | 1424 void P2PTransportChannel::OnReadyToSend(Connection* connection) { |
1435 if (connection == best_connection_ && writable()) { | 1425 if (connection == best_connection_ && writable()) { |
1436 SignalReadyToSend(this); | 1426 SignalReadyToSend(this); |
1437 } | 1427 } |
1438 } | 1428 } |
1439 | 1429 |
1430 P2PTransportChannel::Connections::Connections(P2PTransportChannel* channel) | |
1431 : channel_(channel) {} | |
pthatcher1
2016/01/27 19:59:58
I don't like how the Connections class depends on
guoweis_webrtc
2016/02/29 18:03:00
Agree. Removed Connections and move these 2 to TC.
| |
1432 | |
1433 void P2PTransportChannel::Connections::enable_most_likely_first(bool enable) { | |
1434 ping_most_likely_first_ = enable; | |
1435 } | |
1436 | |
1437 P2PTransportChannel::Connections::iterator | |
1438 P2PTransportChannel::Connections::erase( | |
1439 P2PTransportChannel::Connections::iterator pos) { | |
1440 pinged_connections_.erase(*pos); | |
1441 unpinged_connections_.erase(*pos); | |
1442 return Base::erase(pos); | |
1443 } | |
1444 | |
1445 void P2PTransportChannel::Connections::push_back(Connection*& connection) { | |
1446 Base::push_back(connection); | |
1447 unpinged_connections_.insert(connection); | |
1448 } | |
1449 | |
1450 Connection* P2PTransportChannel::Connections::FindNextPingableConnection( | |
1451 uint32_t now) { | |
1452 RTC_CHECK(size() == | |
1453 pinged_connections_.size() + unpinged_connections_.size()); | |
1454 | |
1455 // If there is nothing pingable in the |unpinged_connections_|, copy over from | |
1456 // |pinged_connections_|. | |
1457 if (std::find_if(unpinged_connections_.begin(), unpinged_connections_.end(), | |
1458 [this, now](Connection* conn) { | |
1459 return channel_->IsPingable(conn, now); | |
1460 }) == unpinged_connections_.end()) { | |
1461 unpinged_connections_.insert(pinged_connections_.begin(), | |
1462 pinged_connections_.end()); | |
1463 pinged_connections_.clear(); | |
pthatcher1
2016/01/27 19:59:58
Shouldn't this happen after MarkConnectionPinged r
guoweis_webrtc
2016/02/29 18:03:00
If the unpinged_connections has only unpingable co
| |
1464 } | |
1465 | |
1466 // First, find "triggered checks". We ping first those connections | |
1467 // that have received a ping but have not sent a ping since receiving | |
1468 // it (last_received_ping > last_sent_ping). But we shouldn't do | |
1469 // triggered checks if the connection is already writable. | |
1470 Connection* oldest_needing_triggered_check = nullptr; | |
1471 for (auto conn : *this) { | |
1472 if (!channel_->IsPingable(conn, now)) { | |
1473 continue; | |
1474 } | |
1475 bool needs_triggered_check = | |
1476 (!conn->writable() && | |
1477 conn->last_ping_received() > conn->last_ping_sent()); | |
1478 if (needs_triggered_check && | |
1479 (!oldest_needing_triggered_check || | |
1480 (conn->last_ping_received() < | |
1481 oldest_needing_triggered_check->last_ping_received()))) { | |
1482 oldest_needing_triggered_check = conn; | |
1483 } | |
1484 } | |
pthatcher1
2016/01/27 19:59:58
I think having a separate FindOldestConnectionNeed
guoweis_webrtc
2016/02/29 18:03:00
Done.
| |
1485 | |
1486 if (oldest_needing_triggered_check) { | |
1487 LOG(LS_INFO) << "Selecting connection for triggered check: " | |
1488 << oldest_needing_triggered_check->ToString(); | |
1489 MarkConnectionPinged(oldest_needing_triggered_check); | |
pthatcher1
2016/01/27 19:59:58
Again, I don't like that just finding it marks it
guoweis_webrtc
2016/02/29 18:03:00
Removed.
| |
1490 return oldest_needing_triggered_check; | |
1491 } | |
1492 | |
1493 Connection* conn_to_ping = nullptr; | |
1494 for (Connection* conn : unpinged_connections_) { | |
1495 if (!channel_->IsPingable(conn, now)) { | |
1496 continue; | |
1497 } | |
1498 if (!conn_to_ping || Compare(conn_to_ping, conn) == conn) { | |
1499 conn_to_ping = conn; | |
1500 } | |
1501 } | |
1502 | |
1503 if (conn_to_ping) { | |
1504 MarkConnectionPinged(conn_to_ping); | |
1505 } | |
1506 | |
1507 return conn_to_ping; | |
1508 } | |
1509 | |
1510 void P2PTransportChannel::Connections::MarkConnectionPinged( | |
1511 Connection* connection) { | |
1512 if (pinged_connections_.insert(connection).second) { | |
1513 unpinged_connections_.erase(connection); | |
1514 } | |
1515 } | |
1516 | |
1517 Connection* P2PTransportChannel::Connections::Compare(Connection* conn1, | |
1518 Connection* conn2) { | |
1519 RTC_DCHECK(conn1 != conn2); | |
1520 if (ping_most_likely_first_) { | |
1521 bool conn1_turn_turn = IsTurnTurn(conn1); | |
pthatcher1
2016/01/27 19:59:58
rr1 would be nicer, shorter name.
guoweis_webrtc
2016/02/29 18:03:00
Done.
| |
1522 bool conn2_turn_turn = IsTurnTurn(conn2); | |
1523 if (conn1_turn_turn ^ conn2_turn_turn) { | |
1524 return conn1_turn_turn ? conn1 : conn2; | |
1525 } | |
1526 if (conn1_turn_turn && conn2_turn_turn) { | |
pthatcher1
2016/01/27 19:59:58
This would be more readable as:
bool rr1 == IsRel
guoweis_webrtc
2016/02/29 18:03:00
Done.
| |
1527 bool conn1_udp_relay = | |
1528 conn1->local_candidate().relay_protocol() == UDP_PROTOCOL_NAME; | |
1529 bool conn2_udp_relay = | |
1530 conn2->local_candidate().relay_protocol() == UDP_PROTOCOL_NAME; | |
1531 if (conn1_udp_relay ^ conn2_udp_relay) { | |
1532 return conn1_udp_relay ? conn1 : conn2; | |
1533 } | |
1534 } | |
1535 } | |
1536 | |
1537 if (conn1->last_ping_sent() < conn2->last_ping_sent()) { | |
1538 return conn1; | |
1539 } | |
1540 if (conn1->last_ping_sent() > conn2->last_ping_sent()) { | |
1541 return conn2; | |
1542 } | |
pthatcher1
2016/01/27 19:59:58
And similarly, we could make a method for LeastRec
guoweis_webrtc
2016/02/29 18:03:00
Done.
| |
1543 | |
1544 // During the initial state when nothing has been pinged yet, return the first | |
1545 // one in the ordered |connections_|. | |
1546 return *(std::find_if(Base::begin(), Base::end(), | |
1547 [conn1, conn2](Connection* conn) { | |
1548 return conn == conn1 || conn == conn2; | |
1549 })); | |
1550 } | |
1551 | |
1552 bool P2PTransportChannel::Connections::IsTurnTurn(Connection* conn) { | |
pthatcher1
2016/01/27 19:59:58
IsRelayToRelay would be a more accurate name.
guoweis_webrtc
2016/02/29 18:03:00
Done.
| |
1553 return conn->local_candidate().type() == RELAY_PORT_TYPE && | |
1554 conn->remote_candidate().type() == RELAY_PORT_TYPE; | |
1555 } | |
1556 | |
1440 } // namespace cricket | 1557 } // namespace cricket |
OLD | NEW |