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

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

Issue 2369963004: Ping the premier connection on each network with higher priority. (Closed)
Patch Set: . Created 4 years, 2 months 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 1230 matching lines...) Expand 10 before | Expand all | Expand 10 after
1241 } 1241 }
1242 1242
1243 Connection* top_connection = 1243 Connection* top_connection =
1244 (connections_.size() > 0) ? connections_[0] : nullptr; 1244 (connections_.size() > 0) ? connections_[0] : nullptr;
1245 1245
1246 // If necessary, switch to the new choice. Note that |top_connection| doesn't 1246 // If necessary, switch to the new choice. Note that |top_connection| doesn't
1247 // have to be writable to become the selected connection although it will 1247 // have to be writable to become the selected connection although it will
1248 // have higher priority if it is writable. 1248 // have higher priority if it is writable.
1249 MaybeSwitchSelectedConnection(top_connection, "sorting"); 1249 MaybeSwitchSelectedConnection(top_connection, "sorting");
1250 1250
1251 UpdatePremierConnections();
1252
1251 // The controlled side can prune only if the selected connection has been 1253 // The controlled side can prune only if the selected connection has been
1252 // nominated because otherwise it may prune the connection that will be 1254 // nominated because otherwise it may prune the connection that will be
1253 // selected by the controlling side. 1255 // selected by the controlling side.
1254 // TODO(honghaiz): This is not enough to prevent a connection from being 1256 // TODO(honghaiz): This is not enough to prevent a connection from being
1255 // pruned too early because with aggressive nomination, the controlling side 1257 // pruned too early because with aggressive nomination, the controlling side
1256 // will nominate every connection until it becomes writable. 1258 // will nominate every connection until it becomes writable.
1257 if (ice_role_ == ICEROLE_CONTROLLING || 1259 if (ice_role_ == ICEROLE_CONTROLLING ||
1258 (selected_connection_ && selected_connection_->nominated())) { 1260 (selected_connection_ && selected_connection_->nominated())) {
1259 PruneConnections(); 1261 PruneConnections();
1260 } 1262 }
(...skipping 17 matching lines...) Expand all
1278 UpdateState(); 1280 UpdateState();
1279 1281
1280 // Also possibly start pinging. 1282 // Also possibly start pinging.
1281 // We could start pinging if: 1283 // We could start pinging if:
1282 // * The first connection was created. 1284 // * The first connection was created.
1283 // * ICE credentials were provided. 1285 // * ICE credentials were provided.
1284 // * A TCP connection became connected. 1286 // * A TCP connection became connected.
1285 MaybeStartPinging(); 1287 MaybeStartPinging();
1286 } 1288 }
1287 1289
1290 void P2PTransportChannel::UpdatePremierConnections() {
1291 // |connections_| has been sorted, so the first one in the list on a given
1292 // network is the premier connection, except that the selected connection
1293 // is always the premier connection on the network.
1294 premier_connection_by_network_name_.clear();
1295 for (Connection* conn : connections_) {
1296 const std::string& network_name = conn->port()->Network()->name();
1297 if (conn == selected_connection_ ||
1298 premier_connection_by_network_name_.find(network_name) ==
1299 premier_connection_by_network_name_.end()) {
1300 premier_connection_by_network_name_[network_name] = conn;
1301 }
1302 }
1303 }
1304
1288 void P2PTransportChannel::PruneConnections() { 1305 void P2PTransportChannel::PruneConnections() {
1289 // We can prune any connection for which there is a connected, writable 1306 // We can prune any connection for which there is a connected, writable
1290 // connection on the same network with better or equal priority. We leave 1307 // connection on the same network with better or equal priority. We leave
1291 // those with better priority just in case they become writable later (at 1308 // those with better priority just in case they become writable later (at
1292 // which point, we would prune out the current selected connection). We leave 1309 // which point, we would prune out the current selected connection). We leave
1293 // connections on other networks because they may not be using the same 1310 // connections on other networks because they may not be using the same
1294 // resources and they may represent very distinct paths over which we can 1311 // resources and they may represent very distinct paths over which we can
1295 // switch. If the |premier| connection is not connected, we may be 1312 // switch. If the |premier| connection is not connected, we may be
1296 // reconnecting a TCP connection and temporarily do not prune connections in 1313 // reconnecting a TCP connection and temporarily do not prune connections in
1297 // this network. See the big comment in CompareConnectionStates. 1314 // this network. See the big comment in CompareConnectionStates.
1298 1315 for (Connection* conn : connections_) {
1299 // Get a list of the networks that we are using. 1316 // Do not prune connections if the current premier connection is weak on
1300 std::set<rtc::Network*> networks;
1301 for (const Connection* conn : connections_) {
1302 networks.insert(conn->port()->Network());
1303 }
1304 for (rtc::Network* network : networks) {
1305 Connection* premier = GetBestConnectionOnNetwork(network);
1306 // Do not prune connections if the current selected connection is weak on
1307 // this network. Otherwise, it may delete connections prematurely. 1317 // this network. Otherwise, it may delete connections prematurely.
1308 if (!premier || premier->weak()) { 1318 Connection* premier =
1319 premier_connection_by_network_name_[conn->port()->Network()->name()];
1320 if (!premier || conn == premier || premier->weak()) {
1309 continue; 1321 continue;
1310 } 1322 }
1311 1323 if (CompareConnectionCandidates(premier, conn) >= 0) {
1312 for (Connection* conn : connections_) { 1324 conn->Prune();
1313 if ((conn != premier) && (conn->port()->Network() == network) &&
1314 (CompareConnectionCandidates(premier, conn) >= 0)) {
1315 conn->Prune();
1316 }
1317 } 1325 }
1318 } 1326 }
1319 } 1327 }
1320 1328
1321 // Change the selected connection, and let listeners know. 1329 // Change the selected connection, and let listeners know.
1322 void P2PTransportChannel::SwitchSelectedConnection(Connection* conn) { 1330 void P2PTransportChannel::SwitchSelectedConnection(Connection* conn) {
1323 // Note: if conn is NULL, the previous |selected_connection_| has been 1331 // Note: if conn is NULL, the previous |selected_connection_| has been
1324 // destroyed, so don't use it. 1332 // destroyed, so don't use it.
1325 Connection* old_selected_connection = selected_connection_; 1333 Connection* old_selected_connection = selected_connection_;
1326 selected_connection_ = conn; 1334 selected_connection_ = conn;
(...skipping 117 matching lines...) Expand 10 before | Expand all | Expand 10 after
1444 bool P2PTransportChannel::ReadyToSend(Connection* connection) const { 1452 bool P2PTransportChannel::ReadyToSend(Connection* connection) const {
1445 // Note that we allow sending on an unreliable connection, because it's 1453 // Note that we allow sending on an unreliable connection, because it's
1446 // possible that it became unreliable simply due to bad chance. 1454 // possible that it became unreliable simply due to bad chance.
1447 // So this shouldn't prevent attempting to send media. 1455 // So this shouldn't prevent attempting to send media.
1448 return connection != nullptr && 1456 return connection != nullptr &&
1449 (connection->writable() || 1457 (connection->writable() ||
1450 connection->write_state() == Connection::STATE_WRITE_UNRELIABLE || 1458 connection->write_state() == Connection::STATE_WRITE_UNRELIABLE ||
1451 PresumedWritable(connection)); 1459 PresumedWritable(connection));
1452 } 1460 }
1453 1461
1454 // If we have a selected connection, return it, otherwise return top one in the
1455 // list (later we will mark it best).
1456 Connection* P2PTransportChannel::GetBestConnectionOnNetwork(
1457 rtc::Network* network) const {
1458 // If the selected connection is on this network, then it wins.
1459 if (selected_connection_ &&
1460 (selected_connection_->port()->Network() == network)) {
1461 return selected_connection_;
1462 }
1463
1464 // Otherwise, we return the top-most in sorted order.
1465 for (size_t i = 0; i < connections_.size(); ++i) {
1466 if (connections_[i]->port()->Network() == network) {
1467 return connections_[i];
1468 }
1469 }
1470
1471 return NULL;
1472 }
1473
1474 // Handle any queued up requests 1462 // Handle any queued up requests
1475 void P2PTransportChannel::OnMessage(rtc::Message *pmsg) { 1463 void P2PTransportChannel::OnMessage(rtc::Message *pmsg) {
1476 switch (pmsg->message_id) { 1464 switch (pmsg->message_id) {
1477 case MSG_SORT_AND_UPDATE_STATE: 1465 case MSG_SORT_AND_UPDATE_STATE:
1478 SortConnectionsAndUpdateState(); 1466 SortConnectionsAndUpdateState();
1479 break; 1467 break;
1480 case MSG_CHECK_AND_PING: 1468 case MSG_CHECK_AND_PING:
1481 OnCheckAndPing(); 1469 OnCheckAndPing();
1482 break; 1470 break;
1483 case MSG_REGATHER_ON_FAILED_NETWORKS: 1471 case MSG_REGATHER_ON_FAILED_NETWORKS:
(...skipping 57 matching lines...) Expand 10 before | Expand all | Expand 10 after
1541 return false; 1529 return false;
1542 } 1530 }
1543 1531
1544 // An never connected connection cannot be written to at all, so pinging is 1532 // An never connected connection cannot be written to at all, so pinging is
1545 // out of the question. However, if it has become WRITABLE, it is in the 1533 // out of the question. However, if it has become WRITABLE, it is in the
1546 // reconnecting state so ping is needed. 1534 // reconnecting state so ping is needed.
1547 if (!conn->connected() && !conn->writable()) { 1535 if (!conn->connected() && !conn->writable()) {
1548 return false; 1536 return false;
1549 } 1537 }
1550 1538
1551 // If the channel is weakly connected, ping all connections. 1539 // Backup connections are pinged at a slower rate if the channel is strongly
1552 if (weak()) { 1540 // connected.
1553 return true; 1541 bool strongly_connected = !weak();
1554 } 1542 if (strongly_connected && IsBackupConnection(conn)) {
1555
1556 // Always ping active connections regardless whether the channel is completed
1557 // or not, but backup connections are pinged at a slower rate.
1558 if (IsBackupConnection(conn)) {
1559 return conn->rtt_samples() == 0 || 1543 return conn->rtt_samples() == 0 ||
1560 (now >= conn->last_ping_response_received() + 1544 (now >= conn->last_ping_response_received() +
1561 config_.backup_connection_ping_interval); 1545 config_.backup_connection_ping_interval);
1562 } 1546 }
1563 // Don't ping inactive non-backup connections. 1547
1548 // If the premier connection is weakly connected, ping all connections on
Taylor Brandstetter 2016/10/04 02:08:10 Suggest changing this to "If the premier connectio
honghaiz3 2016/10/20 23:47:58 Done.
1549 // the same network. Otherwise, do not ping those with a lower priority
1550 // (i.e., those having been pruned) or those which have timed out.
1551 auto iter =
1552 premier_connection_by_network_name_.find(conn->port()->Network()->name());
1553 if (iter == premier_connection_by_network_name_.end() || !iter->second ||
1554 iter->second->weak()) {
1555 return true;
1556 }
1557
1558 // Don't ping inactive connections.
1564 if (!conn->active()) { 1559 if (!conn->active()) {
1565 return false; 1560 return false;
1566 } 1561 }
1567 1562
1568 // Do ping unwritable, active connections. 1563 // Do ping unwritable, active connections.
1569 if (!conn->writable()) { 1564 if (!conn->writable()) {
1570 return true; 1565 return true;
1571 } 1566 }
1572 1567
1573 // Ping writable, active connections if it's been long enough since the last 1568 // Ping writable, active connections if it's been long enough since the last
1574 // ping. 1569 // ping.
1575 int ping_interval = CalculateActiveWritablePingInterval(conn, now); 1570 int ping_interval = CalculateActiveWritablePingInterval(conn, now);
1576 return (now >= conn->last_ping_sent() + ping_interval); 1571 return (now >= conn->last_ping_sent() + ping_interval);
1577 } 1572 }
1578 1573
1579 bool P2PTransportChannel::IsSelectedConnectionPingable(int64_t now) { 1574 bool P2PTransportChannel::IsPremierConnectionPingable(
1580 if (!selected_connection_ || !selected_connection_->connected() || 1575 Connection* premier_connection,
1581 !selected_connection_->writable()) { 1576 int64_t now) {
1577 if (!premier_connection || !premier_connection->connected() ||
1578 !premier_connection->writable() ||
1579 premier_connection->state() == Connection::STATE_FAILED) {
Taylor Brandstetter 2016/10/04 02:08:09 Why did the "failed" check not exist before?
honghaiz3 2016/10/20 23:47:58 It is logical to include this although it does not
1582 return false; 1580 return false;
1583 } 1581 }
1584 1582
1585 int interval = CalculateActiveWritablePingInterval(selected_connection_, now); 1583 int interval = CalculateActiveWritablePingInterval(premier_connection, now);
1586 return selected_connection_->last_ping_sent() + interval <= now; 1584 return premier_connection->last_ping_sent() + interval <= now;
1585 }
1586
1587 Connection* P2PTransportChannel::FindBestPremierConnectionToPing(int64_t now) {
1588 // If the selected connection is pingable, select it to ping.
1589 if (IsPremierConnectionPingable(selected_connection_, now)) {
1590 return selected_connection_;
1591 }
1592
1593 // Otherwise, find the premier connection that has not been pinged for the
1594 // longest time.
1595 Connection* oldest_premier_connection = nullptr;
1596 for (auto kv : premier_connection_by_network_name_) {
1597 Connection* conn = kv.second;
1598 if (conn == nullptr || conn == selected_connection_) {
1599 continue;
1600 }
1601 if (IsPremierConnectionPingable(conn, now) &&
1602 (!oldest_premier_connection ||
1603 conn->last_ping_sent() <
1604 oldest_premier_connection->last_ping_sent())) {
1605 oldest_premier_connection = conn;
1606 }
1607 }
1608 return oldest_premier_connection;
1587 } 1609 }
1588 1610
1589 int P2PTransportChannel::CalculateActiveWritablePingInterval( 1611 int P2PTransportChannel::CalculateActiveWritablePingInterval(
1590 const Connection* conn, 1612 const Connection* conn,
1591 int64_t now) const { 1613 int64_t now) const {
1592 // Ping each connection at a higher rate at least 1614 // Ping each connection at a higher rate at least
1593 // MIN_PINGS_AT_WEAK_PING_INTERVAL times. 1615 // MIN_PINGS_AT_WEAK_PING_INTERVAL times.
1594 if (conn->num_pings_sent() < MIN_PINGS_AT_WEAK_PING_INTERVAL) { 1616 if (conn->num_pings_sent() < MIN_PINGS_AT_WEAK_PING_INTERVAL) {
1595 return weak_ping_interval_; 1617 return weak_ping_interval_;
1596 } 1618 }
1597 1619
1598 int stable_interval = config_.stable_writable_connection_ping_interval; 1620 int stable_interval = config_.stable_writable_connection_ping_interval;
1599 int stablizing_interval = 1621 int stablizing_interval =
1600 std::min(stable_interval, STABILIZING_WRITABLE_CONNECTION_PING_INTERVAL); 1622 std::min(stable_interval, STABILIZING_WRITABLE_CONNECTION_PING_INTERVAL);
1601 1623 // If the channel is weak or the connection is not stable yet, use the
1602 return conn->stable(now) ? stable_interval : stablizing_interval; 1624 // stablizing_interval.
1625 return (!weak() && conn->stable(now)) ? stable_interval : stablizing_interval;
Taylor Brandstetter 2016/10/04 02:08:09 So this is now the "stabilizing or weak" interval?
honghaiz3 2016/10/20 23:47:58 Changed to weak_or_stablizing_interval.
1603 } 1626 }
1604 1627
1605 // Returns the next pingable connection to ping. This will be the oldest 1628 // Returns the next pingable connection to ping. This will be the oldest
1606 // pingable connection unless we have a connected, writable connection that is 1629 // pingable connection unless we have a connected, writable connection that is
1607 // past the writable ping interval. When reconnecting a TCP 1630 // past the writable ping interval. When reconnecting a TCP
1608 // connection, the selected connection is disconnected, although still WRITABLE 1631 // connection, the selected connection is disconnected, although still WRITABLE
1609 // while reconnecting. The newly created connection should be selected as the 1632 // while reconnecting. The newly created connection should be selected as the
1610 // ping target to become writable instead. See the big comment in 1633 // ping target to become writable instead. See the big comment in
1611 // CompareConnectionStates. 1634 // CompareConnectionStates.
1612 Connection* P2PTransportChannel::FindNextPingableConnection() { 1635 Connection* P2PTransportChannel::FindNextPingableConnection() {
1613 int64_t now = rtc::TimeMillis(); 1636 int64_t now = rtc::TimeMillis();
1614 Connection* conn_to_ping = nullptr; 1637 Connection* conn_to_ping = FindBestPremierConnectionToPing(now);
1615 if (IsSelectedConnectionPingable(now)) { 1638 if (!conn_to_ping) {
1616 conn_to_ping = selected_connection_;
1617 } else {
1618 conn_to_ping = FindConnectionToPing(now); 1639 conn_to_ping = FindConnectionToPing(now);
1619 } 1640 }
1620 return conn_to_ping; 1641 return conn_to_ping;
1621 } 1642 }
1622 1643
1623 void P2PTransportChannel::MarkConnectionPinged(Connection* conn) { 1644 void P2PTransportChannel::MarkConnectionPinged(Connection* conn) {
1624 if (conn && pinged_connections_.insert(conn).second) { 1645 if (conn && pinged_connections_.insert(conn).second) {
1625 unpinged_connections_.erase(conn); 1646 unpinged_connections_.erase(conn);
1626 } 1647 }
1627 } 1648 }
(...skipping 93 matching lines...) Expand 10 before | Expand all | Expand 10 after
1721 // Note: the previous selected_connection_ may be destroyed by now, so don't 1742 // Note: the previous selected_connection_ may be destroyed by now, so don't
1722 // use it. 1743 // use it.
1723 1744
1724 // Remove this connection from the list. 1745 // Remove this connection from the list.
1725 std::vector<Connection*>::iterator iter = 1746 std::vector<Connection*>::iterator iter =
1726 std::find(connections_.begin(), connections_.end(), connection); 1747 std::find(connections_.begin(), connections_.end(), connection);
1727 ASSERT(iter != connections_.end()); 1748 ASSERT(iter != connections_.end());
1728 pinged_connections_.erase(*iter); 1749 pinged_connections_.erase(*iter);
1729 unpinged_connections_.erase(*iter); 1750 unpinged_connections_.erase(*iter);
1730 connections_.erase(iter); 1751 connections_.erase(iter);
1752 for (auto kv : premier_connection_by_network_name_) {
1753 if (kv.second == connection) {
1754 kv.second = nullptr;
1755 }
1756 }
1731 1757
1732 LOG_J(LS_INFO, this) << "Removed connection (" 1758 LOG_J(LS_INFO, this) << "Removed connection " << std::hex << connection
Taylor Brandstetter 2016/10/04 02:08:10 Why not log connection->ToString()?
honghaiz3 2016/10/20 23:47:58 connection->ToString() needs to access the members
Taylor Brandstetter 2016/10/21 20:18:49 Does that risk really exist? I thought a Port is o
honghaiz3 2016/10/21 21:27:26 It probably does not although it would require car
1733 << static_cast<int>(connections_.size()) << " remaining)"; 1759 << std::dec << " ("
1760 << static_cast<int>(connections_.size())
1761 << " remaining)";
1734 1762
1735 // If this is currently the selected connection, then we need to pick a new 1763 // If this is currently the selected connection, then we need to pick a new
1736 // one. The call to SortConnectionsAndUpdateState will pick a new one. It 1764 // one. The call to SortConnectionsAndUpdateState will pick a new one. It
1737 // looks at the current selected connection in order to avoid switching 1765 // looks at the current selected connection in order to avoid switching
1738 // between fairly similar ones. Since this connection is no longer an option, 1766 // between fairly similar ones. Since this connection is no longer an option,
1739 // we can just set selected to nullptr and re-choose a best assuming that 1767 // we can just set selected to nullptr and re-choose a best assuming that
1740 // there was no selected connection. 1768 // there was no selected connection.
1741 if (selected_connection_ == connection) { 1769 if (selected_connection_ == connection) {
1742 LOG(LS_INFO) << "Selected connection destroyed. Will choose a new one."; 1770 LOG(LS_INFO) << "Selected connection destroyed. Will choose a new one.";
1743 SwitchSelectedConnection(nullptr); 1771 SwitchSelectedConnection(nullptr);
(...skipping 107 matching lines...) Expand 10 before | Expand all | Expand 10 after
1851 } 1879 }
1852 1880
1853 void P2PTransportChannel::OnReadyToSend(Connection* connection) { 1881 void P2PTransportChannel::OnReadyToSend(Connection* connection) {
1854 if (connection == selected_connection_ && writable()) { 1882 if (connection == selected_connection_ && writable()) {
1855 SignalReadyToSend(this); 1883 SignalReadyToSend(this);
1856 } 1884 }
1857 } 1885 }
1858 1886
1859 // Find "triggered checks". We ping first those connections that have 1887 // Find "triggered checks". We ping first those connections that have
1860 // received a ping but have not sent a ping since receiving it 1888 // received a ping but have not sent a ping since receiving it
1861 // (last_received_ping > last_sent_ping). But we shouldn't do 1889 // (last_ping_received > last_ping_sent). But we shouldn't do
1862 // triggered checks if the connection is already writable. 1890 // triggered checks if the connection is already writable.
1863 Connection* P2PTransportChannel::FindOldestConnectionNeedingTriggeredCheck( 1891 Connection* P2PTransportChannel::FindOldestConnectionNeedingTriggeredCheck(
1864 int64_t now) { 1892 int64_t now) {
1865 Connection* oldest_needing_triggered_check = nullptr; 1893 Connection* oldest_needing_triggered_check = nullptr;
1866 for (auto conn : connections_) { 1894 for (auto conn : connections_) {
1867 if (!IsPingable(conn, now)) { 1895 if (!IsPingable(conn, now)) {
1868 continue; 1896 continue;
1869 } 1897 }
1870 bool needs_triggered_check = 1898 bool needs_triggered_check =
1871 (!conn->writable() && 1899 (!conn->writable() &&
(...skipping 95 matching lines...) Expand 10 before | Expand all | Expand 10 after
1967 1995
1968 // During the initial state when nothing has been pinged yet, return the first 1996 // During the initial state when nothing has been pinged yet, return the first
1969 // one in the ordered |connections_|. 1997 // one in the ordered |connections_|.
1970 return *(std::find_if(connections_.begin(), connections_.end(), 1998 return *(std::find_if(connections_.begin(), connections_.end(),
1971 [conn1, conn2](Connection* conn) { 1999 [conn1, conn2](Connection* conn) {
1972 return conn == conn1 || conn == conn2; 2000 return conn == conn1 || conn == conn2;
1973 })); 2001 }));
1974 } 2002 }
1975 2003
1976 } // namespace cricket 2004 } // namespace cricket
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698