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 48 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
59 } // unnamed namespace | 59 } // unnamed namespace |
60 | 60 |
61 namespace cricket { | 61 namespace cricket { |
62 | 62 |
63 // When the socket is unwritable, we will use 10 Kbps (ignoring IP+UDP headers) | 63 // When the socket is unwritable, we will use 10 Kbps (ignoring IP+UDP headers) |
64 // for pinging. When the socket is writable, we will use only 1 Kbps because | 64 // for pinging. When the socket is writable, we will use only 1 Kbps because |
65 // we don't want to degrade the quality on a modem. These numbers should work | 65 // we don't want to degrade the quality on a modem. These numbers should work |
66 // well on a 28.8K modem, which is the slowest connection on which the voice | 66 // well on a 28.8K modem, which is the slowest connection on which the voice |
67 // quality is reasonable at all. | 67 // quality is reasonable at all. |
68 static const int PING_PACKET_SIZE = 60 * 8; | 68 static const int PING_PACKET_SIZE = 60 * 8; |
69 | |
70 // The next two ping intervals are at the channel level. | |
69 // STRONG_PING_INTERVAL (480ms) is applied when the selected connection is both | 71 // STRONG_PING_INTERVAL (480ms) is applied when the selected connection is both |
70 // writable and receiving. | 72 // writable and receiving. |
71 static const int STRONG_PING_INTERVAL = 1000 * PING_PACKET_SIZE / 1000; | 73 static const int STRONG_PING_INTERVAL = 1000 * PING_PACKET_SIZE / 1000; |
72 // WEAK_PING_INTERVAL (48ms) is applied when the selected connection is either | 74 // WEAK_PING_INTERVAL (48ms) is applied when the selected connection is either |
73 // not writable or not receiving. | 75 // not writable or not receiving. |
74 const int WEAK_PING_INTERVAL = 1000 * PING_PACKET_SIZE / 10000; | 76 const int WEAK_PING_INTERVAL = 1000 * PING_PACKET_SIZE / 10000; |
75 | 77 |
76 // Writable connections are pinged at a faster rate while stabilizing. | 78 // The next two ping intervals are at the connection level. |
77 const int STABILIZING_WRITABLE_CONNECTION_PING_INTERVAL = 900; // ms | 79 // Writable connections are pinged at a faster rate while the connections are |
78 | 80 // stabilizing or the channel is weak. |
79 // Writable connections are pinged at a slower rate once stabilized. | 81 const int WEAK_OR_STABILIZING_WRITABLE_CONNECTION_PING_INTERVAL = 900; // ms |
80 const int STABLE_WRITABLE_CONNECTION_PING_INTERVAL = 2500; // ms | 82 // Writable connections are pinged at a slower rate once they are stabilized and |
83 // the channel is strongly connected. | |
84 const int STRONG_AND_STABLE_WRITABLE_CONNECTION_PING_INTERVAL = 2500; // ms | |
81 | 85 |
82 static const int MIN_CHECK_RECEIVING_INTERVAL = 50; // ms | 86 static const int MIN_CHECK_RECEIVING_INTERVAL = 50; // ms |
83 | 87 |
84 static const int RECEIVING_SWITCHING_DELAY = 1000; // ms | 88 static const int RECEIVING_SWITCHING_DELAY = 1000; // ms |
85 | 89 |
86 // We periodically check if any existing networks do not have any connection | 90 // We periodically check if any existing networks do not have any connection |
87 // and regather on those networks. | 91 // and regather on those networks. |
88 static const int DEFAULT_REGATHER_ON_FAILED_NETWORKS_INTERVAL = 5 * 60 * 1000; | 92 static const int DEFAULT_REGATHER_ON_FAILED_NETWORKS_INTERVAL = 5 * 60 * 1000; |
89 | 93 |
90 static constexpr int DEFAULT_BACKUP_CONNECTION_PING_INTERVAL = 25 * 1000; | 94 static constexpr int DEFAULT_BACKUP_CONNECTION_PING_INTERVAL = 25 * 1000; |
(...skipping 18 matching lines...) Expand all Loading... | |
109 sort_dirty_(false), | 113 sort_dirty_(false), |
110 remote_ice_mode_(ICEMODE_FULL), | 114 remote_ice_mode_(ICEMODE_FULL), |
111 ice_role_(ICEROLE_UNKNOWN), | 115 ice_role_(ICEROLE_UNKNOWN), |
112 tiebreaker_(0), | 116 tiebreaker_(0), |
113 gathering_state_(kIceGatheringNew), | 117 gathering_state_(kIceGatheringNew), |
114 check_receiving_interval_(MIN_CHECK_RECEIVING_INTERVAL * 5), | 118 check_receiving_interval_(MIN_CHECK_RECEIVING_INTERVAL * 5), |
115 config_(MIN_CHECK_RECEIVING_INTERVAL * 50 /* receiving_timeout */, | 119 config_(MIN_CHECK_RECEIVING_INTERVAL * 50 /* receiving_timeout */, |
116 DEFAULT_BACKUP_CONNECTION_PING_INTERVAL, | 120 DEFAULT_BACKUP_CONNECTION_PING_INTERVAL, |
117 GATHER_ONCE /* continual_gathering_policy */, | 121 GATHER_ONCE /* continual_gathering_policy */, |
118 false /* prioritize_most_likely_candidate_pairs */, | 122 false /* prioritize_most_likely_candidate_pairs */, |
119 STABLE_WRITABLE_CONNECTION_PING_INTERVAL, | 123 STRONG_AND_STABLE_WRITABLE_CONNECTION_PING_INTERVAL, |
120 true /* presume_writable_when_fully_relayed */, | 124 true /* presume_writable_when_fully_relayed */, |
121 DEFAULT_REGATHER_ON_FAILED_NETWORKS_INTERVAL, | 125 DEFAULT_REGATHER_ON_FAILED_NETWORKS_INTERVAL, |
122 RECEIVING_SWITCHING_DELAY) { | 126 RECEIVING_SWITCHING_DELAY) { |
123 uint32_t weak_ping_interval = ::strtoul( | 127 uint32_t weak_ping_interval = ::strtoul( |
124 webrtc::field_trial::FindFullName("WebRTC-StunInterPacketDelay").c_str(), | 128 webrtc::field_trial::FindFullName("WebRTC-StunInterPacketDelay").c_str(), |
125 nullptr, 10); | 129 nullptr, 10); |
126 if (weak_ping_interval) { | 130 if (weak_ping_interval) { |
127 weak_ping_interval_ = static_cast<int>(weak_ping_interval); | 131 weak_ping_interval_ = static_cast<int>(weak_ping_interval); |
128 } | 132 } |
129 } | 133 } |
(...skipping 1106 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1236 // will be sorted. | 1240 // will be sorted. |
1237 UpdateConnectionStates(); | 1241 UpdateConnectionStates(); |
1238 | 1242 |
1239 // Any changes after this point will require a re-sort. | 1243 // Any changes after this point will require a re-sort. |
1240 sort_dirty_ = false; | 1244 sort_dirty_ = false; |
1241 | 1245 |
1242 // Find the best alternative connection by sorting. It is important to note | 1246 // Find the best alternative connection by sorting. It is important to note |
1243 // that amongst equal preference, writable connections, this will choose the | 1247 // that amongst equal preference, writable connections, this will choose the |
1244 // one whose estimated latency is lowest. So it is the only one that we | 1248 // one whose estimated latency is lowest. So it is the only one that we |
1245 // need to consider switching to. | 1249 // need to consider switching to. |
1250 // TODO(honghaiz): Don't sort; Just use std::max in the right places. | |
1246 std::stable_sort(connections_.begin(), connections_.end(), | 1251 std::stable_sort(connections_.begin(), connections_.end(), |
1247 [this](const Connection* a, const Connection* b) { | 1252 [this](const Connection* a, const Connection* b) { |
1248 int cmp = CompareConnections( | 1253 int cmp = CompareConnections( |
1249 a, b, rtc::Optional<int64_t>(), nullptr); | 1254 a, b, rtc::Optional<int64_t>(), nullptr); |
1250 if (cmp != 0) { | 1255 if (cmp != 0) { |
1251 return cmp > 0; | 1256 return cmp > 0; |
1252 } | 1257 } |
1253 // Otherwise, sort based on latency estimate. | 1258 // Otherwise, sort based on latency estimate. |
1254 return a->rtt() < b->rtt(); | 1259 return a->rtt() < b->rtt(); |
1255 }); | 1260 }); |
(...skipping 42 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1298 UpdateState(); | 1303 UpdateState(); |
1299 | 1304 |
1300 // Also possibly start pinging. | 1305 // Also possibly start pinging. |
1301 // We could start pinging if: | 1306 // We could start pinging if: |
1302 // * The first connection was created. | 1307 // * The first connection was created. |
1303 // * ICE credentials were provided. | 1308 // * ICE credentials were provided. |
1304 // * A TCP connection became connected. | 1309 // * A TCP connection became connected. |
1305 MaybeStartPinging(); | 1310 MaybeStartPinging(); |
1306 } | 1311 } |
1307 | 1312 |
1313 std::map<rtc::Network*, Connection*> | |
1314 P2PTransportChannel::GetBestConnectionByNetwork() const { | |
1315 // |connections_| has been sorted, so the first one in the list on a given | |
1316 // network is the best connection on the network, except that the selected | |
1317 // connection is always the best connection on the network. | |
1318 std::map<rtc::Network*, Connection*> best_connection_by_network; | |
1319 if (selected_connection_) { | |
1320 best_connection_by_network[selected_connection_->port()->Network()] = | |
1321 selected_connection_; | |
1322 } | |
1323 for (Connection* conn : connections_) { | |
pthatcher1
2016/10/31 18:21:27
Should put a TODO to get off of connections_ being
honghaiz3
2016/10/31 19:17:29
Done.
| |
1324 rtc::Network* network = conn->port()->Network(); | |
1325 // This only inserts when the network does not exist in the map. | |
1326 best_connection_by_network.insert(std::make_pair(network, conn)); | |
1327 } | |
1328 return best_connection_by_network; | |
1329 } | |
1330 | |
1331 std::vector<Connection*> | |
1332 P2PTransportChannel::GetBestWritableConnectionPerNetwork() const { | |
1333 std::vector<Connection*> connections; | |
1334 for (auto kv : GetBestConnectionByNetwork()) { | |
pthatcher1
2016/10/31 18:21:27
If we have two connections on a network and the be
honghaiz3
2016/10/31 19:17:29
I do not think so. If a connection is not writable
| |
1335 Connection* conn = kv.second; | |
1336 if (conn->writable() && conn->connected()) { | |
1337 connections.push_back(conn); | |
1338 } | |
1339 } | |
1340 return connections; | |
1341 } | |
1342 | |
1308 void P2PTransportChannel::PruneConnections() { | 1343 void P2PTransportChannel::PruneConnections() { |
1309 // We can prune any connection for which there is a connected, writable | 1344 // We can prune any connection for which there is a connected, writable |
1310 // connection on the same network with better or equal priority. We leave | 1345 // connection on the same network with better or equal priority. We leave |
1311 // those with better priority just in case they become writable later (at | 1346 // those with better priority just in case they become writable later (at |
1312 // which point, we would prune out the current selected connection). We leave | 1347 // which point, we would prune out the current selected connection). We leave |
1313 // connections on other networks because they may not be using the same | 1348 // connections on other networks because they may not be using the same |
1314 // resources and they may represent very distinct paths over which we can | 1349 // resources and they may represent very distinct paths over which we can |
1315 // switch. If the |premier| connection is not connected, we may be | 1350 // switch. If |best_conn_on_network| is not connected, we may be reconnecting |
1316 // reconnecting a TCP connection and temporarily do not prune connections in | 1351 // a TCP connection and should not prune connections in this network. |
1317 // this network. See the big comment in CompareConnectionStates. | 1352 // See the big comment in CompareConnectionStates. |
1318 | 1353 auto best_connection_by_network = GetBestConnectionByNetwork(); |
1319 // Get a list of the networks that we are using. | 1354 for (Connection* conn : connections_) { |
1320 std::set<rtc::Network*> networks; | 1355 // Do not prune connections if the current best connection on this network |
1321 for (const Connection* conn : connections_) { | 1356 // is weak. Otherwise, it may delete connections prematurely. |
1322 networks.insert(conn->port()->Network()); | 1357 Connection* best_conn_on_network = |
1323 } | 1358 best_connection_by_network[conn->port()->Network()]; |
1324 for (rtc::Network* network : networks) { | 1359 if (best_conn_on_network && conn != best_conn_on_network && |
1325 Connection* premier = GetBestConnectionOnNetwork(network); | 1360 !best_conn_on_network->weak() && |
1326 // Do not prune connections if the current selected connection is weak on | 1361 CompareConnectionCandidates(best_conn_on_network, conn) >= 0) { |
1327 // this network. Otherwise, it may delete connections prematurely. | 1362 conn->Prune(); |
1328 if (!premier || premier->weak()) { | |
1329 continue; | |
1330 } | |
1331 | |
1332 for (Connection* conn : connections_) { | |
1333 if ((conn != premier) && (conn->port()->Network() == network) && | |
1334 (CompareConnectionCandidates(premier, conn) >= 0)) { | |
1335 conn->Prune(); | |
1336 } | |
1337 } | 1363 } |
1338 } | 1364 } |
1339 } | 1365 } |
1340 | 1366 |
1341 // Change the selected connection, and let listeners know. | 1367 // Change the selected connection, and let listeners know. |
1342 void P2PTransportChannel::SwitchSelectedConnection(Connection* conn) { | 1368 void P2PTransportChannel::SwitchSelectedConnection(Connection* conn) { |
1343 // Note: if conn is NULL, the previous |selected_connection_| has been | 1369 // Note: if conn is NULL, the previous |selected_connection_| has been |
1344 // destroyed, so don't use it. | 1370 // destroyed, so don't use it. |
1345 Connection* old_selected_connection = selected_connection_; | 1371 Connection* old_selected_connection = selected_connection_; |
1346 selected_connection_ = conn; | 1372 selected_connection_ = conn; |
(...skipping 117 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1464 bool P2PTransportChannel::ReadyToSend(Connection* connection) const { | 1490 bool P2PTransportChannel::ReadyToSend(Connection* connection) const { |
1465 // Note that we allow sending on an unreliable connection, because it's | 1491 // Note that we allow sending on an unreliable connection, because it's |
1466 // possible that it became unreliable simply due to bad chance. | 1492 // possible that it became unreliable simply due to bad chance. |
1467 // So this shouldn't prevent attempting to send media. | 1493 // So this shouldn't prevent attempting to send media. |
1468 return connection != nullptr && | 1494 return connection != nullptr && |
1469 (connection->writable() || | 1495 (connection->writable() || |
1470 connection->write_state() == Connection::STATE_WRITE_UNRELIABLE || | 1496 connection->write_state() == Connection::STATE_WRITE_UNRELIABLE || |
1471 PresumedWritable(connection)); | 1497 PresumedWritable(connection)); |
1472 } | 1498 } |
1473 | 1499 |
1474 // If we have a selected connection, return it, otherwise return top one in the | |
1475 // list (later we will mark it best). | |
1476 Connection* P2PTransportChannel::GetBestConnectionOnNetwork( | |
1477 rtc::Network* network) const { | |
1478 // If the selected connection is on this network, then it wins. | |
1479 if (selected_connection_ && | |
1480 (selected_connection_->port()->Network() == network)) { | |
1481 return selected_connection_; | |
1482 } | |
1483 | |
1484 // Otherwise, we return the top-most in sorted order. | |
1485 for (size_t i = 0; i < connections_.size(); ++i) { | |
1486 if (connections_[i]->port()->Network() == network) { | |
1487 return connections_[i]; | |
1488 } | |
1489 } | |
1490 | |
1491 return NULL; | |
1492 } | |
1493 | |
1494 // Handle any queued up requests | 1500 // Handle any queued up requests |
1495 void P2PTransportChannel::OnMessage(rtc::Message *pmsg) { | 1501 void P2PTransportChannel::OnMessage(rtc::Message *pmsg) { |
1496 switch (pmsg->message_id) { | 1502 switch (pmsg->message_id) { |
1497 case MSG_SORT_AND_UPDATE_STATE: | 1503 case MSG_SORT_AND_UPDATE_STATE: |
1498 SortConnectionsAndUpdateState(); | 1504 SortConnectionsAndUpdateState(); |
1499 break; | 1505 break; |
1500 case MSG_CHECK_AND_PING: | 1506 case MSG_CHECK_AND_PING: |
1501 OnCheckAndPing(); | 1507 OnCheckAndPing(); |
1502 break; | 1508 break; |
1503 case MSG_REGATHER_ON_FAILED_NETWORKS: | 1509 case MSG_REGATHER_ON_FAILED_NETWORKS: |
(...skipping 81 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1585 return false; | 1591 return false; |
1586 } | 1592 } |
1587 | 1593 |
1588 // Do ping unwritable, active connections. | 1594 // Do ping unwritable, active connections. |
1589 if (!conn->writable()) { | 1595 if (!conn->writable()) { |
1590 return true; | 1596 return true; |
1591 } | 1597 } |
1592 | 1598 |
1593 // Ping writable, active connections if it's been long enough since the last | 1599 // Ping writable, active connections if it's been long enough since the last |
1594 // ping. | 1600 // ping. |
1595 int ping_interval = CalculateActiveWritablePingInterval(conn, now); | 1601 return WritableConnectionPastPingInterval(conn, now); |
1596 return (now >= conn->last_ping_sent() + ping_interval); | |
1597 } | 1602 } |
1598 | 1603 |
1599 bool P2PTransportChannel::IsSelectedConnectionPingable(int64_t now) { | 1604 bool P2PTransportChannel::WritableConnectionPastPingInterval( |
1600 if (!selected_connection_ || !selected_connection_->connected() || | 1605 const Connection* conn, |
1601 !selected_connection_->writable()) { | 1606 int64_t now) const { |
1602 return false; | 1607 int interval = CalculateActiveWritablePingInterval(conn, now); |
1603 } | 1608 return conn->last_ping_sent() + interval <= now; |
1604 | |
1605 int interval = CalculateActiveWritablePingInterval(selected_connection_, now); | |
1606 return selected_connection_->last_ping_sent() + interval <= now; | |
1607 } | 1609 } |
1608 | 1610 |
1609 int P2PTransportChannel::CalculateActiveWritablePingInterval( | 1611 int P2PTransportChannel::CalculateActiveWritablePingInterval( |
1610 const Connection* conn, | 1612 const Connection* conn, |
1611 int64_t now) const { | 1613 int64_t now) const { |
1612 // Ping each connection at a higher rate at least | 1614 // Ping each connection at a higher rate at least |
1613 // MIN_PINGS_AT_WEAK_PING_INTERVAL times. | 1615 // MIN_PINGS_AT_WEAK_PING_INTERVAL times. |
1614 if (conn->num_pings_sent() < MIN_PINGS_AT_WEAK_PING_INTERVAL) { | 1616 if (conn->num_pings_sent() < MIN_PINGS_AT_WEAK_PING_INTERVAL) { |
1615 return weak_ping_interval_; | 1617 return weak_ping_interval_; |
1616 } | 1618 } |
1617 | 1619 |
1618 int stable_interval = config_.stable_writable_connection_ping_interval; | 1620 int stable_interval = config_.stable_writable_connection_ping_interval; |
1619 int stablizing_interval = | 1621 int weak_or_stablizing_interval = std::min( |
1620 std::min(stable_interval, STABILIZING_WRITABLE_CONNECTION_PING_INTERVAL); | 1622 stable_interval, WEAK_OR_STABILIZING_WRITABLE_CONNECTION_PING_INTERVAL); |
1621 | 1623 // If the channel is weak or the connection is not stable yet, use the |
1622 return conn->stable(now) ? stable_interval : stablizing_interval; | 1624 // weak_or_stablizing_interval. |
1625 return (!weak() && conn->stable(now)) ? stable_interval | |
1626 : weak_or_stablizing_interval; | |
1623 } | 1627 } |
1624 | 1628 |
1625 // Returns the next pingable connection to ping. This will be the oldest | 1629 // Returns the next pingable connection to ping. |
1626 // pingable connection unless we have a connected, writable connection that is | |
1627 // past the writable ping interval. When reconnecting a TCP | |
1628 // connection, the selected connection is disconnected, although still WRITABLE | |
1629 // while reconnecting. The newly created connection should be selected as the | |
1630 // ping target to become writable instead. See the big comment in | |
1631 // CompareConnectionStates. | |
1632 Connection* P2PTransportChannel::FindNextPingableConnection() { | 1630 Connection* P2PTransportChannel::FindNextPingableConnection() { |
1633 int64_t now = rtc::TimeMillis(); | 1631 int64_t now = rtc::TimeMillis(); |
1634 Connection* conn_to_ping = nullptr; | 1632 |
1635 if (IsSelectedConnectionPingable(now)) { | 1633 // Rule 1: Selected connection takes priority over non-selected ones. |
1636 conn_to_ping = selected_connection_; | 1634 if (selected_connection_ && selected_connection_->connected() && |
1637 } else { | 1635 selected_connection_->writable() && |
1638 conn_to_ping = FindConnectionToPing(now); | 1636 WritableConnectionPastPingInterval(selected_connection_, now)) { |
1637 return selected_connection_; | |
1639 } | 1638 } |
1640 return conn_to_ping; | 1639 |
1640 // Rule 2: If the channel is weak, we need to find a new writable and | |
1641 // receiving connection, probably on a different network. If there are lots of | |
1642 // connections, it may take several seconds between two pings for every | |
1643 // non-selected connection. This will cause the receiving state of those | |
1644 // connections to be false, and thus they won't be selected. This is | |
1645 // problematic for network fail-over. We want to make sure at least one | |
1646 // connection per network be pinged frequently enough in order for it to be | |
Taylor Brandstetter
2016/10/29 00:27:45
be -> is
honghaiz3
2016/10/31 19:17:29
Done.
| |
1647 // selectable. So we prioritize one connection per network. | |
1648 // Rule 2.1: Among such connections, pick the one with the smallest | |
Taylor Brandstetter
2016/10/29 00:27:45
smallest -> earliest
honghaiz3
2016/10/31 19:17:29
Done.
| |
1649 // last-ping-sent time. | |
1650 if (weak()) { | |
1651 auto selectable_connections = GetBestWritableConnectionPerNetwork(); | |
1652 std::vector<Connection*> pingable_selectable_connections; | |
1653 std::copy_if(selectable_connections.begin(), selectable_connections.end(), | |
1654 std::back_inserter(pingable_selectable_connections), | |
1655 [this, now](Connection* conn) { | |
1656 return WritableConnectionPastPingInterval(conn, now); | |
1657 }); | |
1658 auto iter = std::min_element(pingable_selectable_connections.begin(), | |
1659 pingable_selectable_connections.end(), | |
1660 [](Connection* conn1, Connection* conn2) { | |
1661 return conn1->last_ping_sent() < | |
Taylor Brandstetter
2016/10/29 00:27:45
This isn't a new issue, but this comparison doesn'
honghaiz3
2016/10/31 19:17:29
We are using 64 bit time now. I think won't need t
| |
1662 conn2->last_ping_sent(); | |
1663 }); | |
1664 if (iter != pingable_selectable_connections.end()) { | |
1665 return *iter; | |
1666 } | |
1667 } | |
1668 | |
1669 // Rule 3: Triggered checks have priority over non-triggered connections. | |
1670 // Rule 3.1: Among triggered checks, oldest takes precedence. | |
1671 Connection* oldest_triggered_check = | |
1672 FindOldestConnectionNeedingTriggeredCheck(now); | |
1673 if (oldest_triggered_check) { | |
1674 return oldest_triggered_check; | |
1675 } | |
1676 | |
1677 // Rule 4: Unpinged connections have priority over pinged ones. | |
1678 RTC_CHECK(connections_.size() == | |
1679 pinged_connections_.size() + unpinged_connections_.size()); | |
1680 // If there are unpinged and pingable connections, only ping those. | |
1681 // Otherwise, treat everything as unpinged. | |
1682 if (std::find_if(unpinged_connections_.begin(), unpinged_connections_.end(), | |
1683 [this, now](Connection* conn) { | |
1684 return this->IsPingable(conn, now); | |
1685 }) == unpinged_connections_.end()) { | |
1686 unpinged_connections_.insert(pinged_connections_.begin(), | |
1687 pinged_connections_.end()); | |
Taylor Brandstetter
2016/10/29 00:27:45
This is still a confusing part (pinged connections
honghaiz3
2016/10/31 19:17:29
I agree. I think we can just use a state pinged_ i
| |
1688 pinged_connections_.clear(); | |
1689 } | |
1690 | |
1691 // Among un-pinged pingable connections, "more pingable" takes precedence. | |
1692 std::vector<Connection*> pingable_connections; | |
1693 std::copy_if(unpinged_connections_.begin(), unpinged_connections_.end(), | |
1694 std::back_inserter(pingable_connections), | |
1695 [this, now](Connection* conn) { return IsPingable(conn, now); }); | |
1696 auto iter = | |
1697 std::max_element(pingable_connections.begin(), pingable_connections.end(), | |
1698 [this, now](Connection* conn1, Connection* conn2) { | |
1699 return MorePingable(conn1, conn2) == conn2; | |
1700 }); | |
1701 if (iter != pingable_connections.end()) { | |
1702 return *iter; | |
1703 } | |
1704 return nullptr; | |
1641 } | 1705 } |
1642 | 1706 |
1643 void P2PTransportChannel::MarkConnectionPinged(Connection* conn) { | 1707 void P2PTransportChannel::MarkConnectionPinged(Connection* conn) { |
1644 if (conn && pinged_connections_.insert(conn).second) { | 1708 if (conn && pinged_connections_.insert(conn).second) { |
1645 unpinged_connections_.erase(conn); | 1709 unpinged_connections_.erase(conn); |
1646 } | 1710 } |
1647 } | 1711 } |
1648 | 1712 |
1649 // Apart from sending ping from |conn| this method also updates | 1713 // Apart from sending ping from |conn| this method also updates |
1650 // |use_candidate_attr| and |nomination| flags. One of the flags is set to | 1714 // |use_candidate_attr| and |nomination| flags. One of the flags is set to |
(...skipping 91 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1742 // use it. | 1806 // use it. |
1743 | 1807 |
1744 // Remove this connection from the list. | 1808 // Remove this connection from the list. |
1745 std::vector<Connection*>::iterator iter = | 1809 std::vector<Connection*>::iterator iter = |
1746 std::find(connections_.begin(), connections_.end(), connection); | 1810 std::find(connections_.begin(), connections_.end(), connection); |
1747 ASSERT(iter != connections_.end()); | 1811 ASSERT(iter != connections_.end()); |
1748 pinged_connections_.erase(*iter); | 1812 pinged_connections_.erase(*iter); |
1749 unpinged_connections_.erase(*iter); | 1813 unpinged_connections_.erase(*iter); |
1750 connections_.erase(iter); | 1814 connections_.erase(iter); |
1751 | 1815 |
1752 LOG_J(LS_INFO, this) << "Removed connection (" | 1816 LOG_J(LS_INFO, this) << "Removed connection " << std::hex << connection |
1753 << static_cast<int>(connections_.size()) << " remaining)"; | 1817 << std::dec << " (" << connections_.size() |
1818 << " remaining)"; | |
1754 | 1819 |
1755 // If this is currently the selected connection, then we need to pick a new | 1820 // If this is currently the selected connection, then we need to pick a new |
1756 // one. The call to SortConnectionsAndUpdateState will pick a new one. It | 1821 // one. The call to SortConnectionsAndUpdateState will pick a new one. It |
1757 // looks at the current selected connection in order to avoid switching | 1822 // looks at the current selected connection in order to avoid switching |
1758 // between fairly similar ones. Since this connection is no longer an option, | 1823 // between fairly similar ones. Since this connection is no longer an option, |
1759 // we can just set selected to nullptr and re-choose a best assuming that | 1824 // we can just set selected to nullptr and re-choose a best assuming that |
1760 // there was no selected connection. | 1825 // there was no selected connection. |
1761 if (selected_connection_ == connection) { | 1826 if (selected_connection_ == connection) { |
1762 LOG(LS_INFO) << "Selected connection destroyed. Will choose a new one."; | 1827 LOG(LS_INFO) << "Selected connection destroyed. Will choose a new one."; |
1763 SwitchSelectedConnection(nullptr); | 1828 SwitchSelectedConnection(nullptr); |
(...skipping 107 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1871 } | 1936 } |
1872 | 1937 |
1873 void P2PTransportChannel::OnReadyToSend(Connection* connection) { | 1938 void P2PTransportChannel::OnReadyToSend(Connection* connection) { |
1874 if (connection == selected_connection_ && writable()) { | 1939 if (connection == selected_connection_ && writable()) { |
1875 SignalReadyToSend(this); | 1940 SignalReadyToSend(this); |
1876 } | 1941 } |
1877 } | 1942 } |
1878 | 1943 |
1879 // Find "triggered checks". We ping first those connections that have | 1944 // Find "triggered checks". We ping first those connections that have |
1880 // received a ping but have not sent a ping since receiving it | 1945 // received a ping but have not sent a ping since receiving it |
1881 // (last_received_ping > last_sent_ping). But we shouldn't do | 1946 // (last_ping_received > last_ping_sent). But we shouldn't do |
1882 // triggered checks if the connection is already writable. | 1947 // triggered checks if the connection is already writable. |
1883 Connection* P2PTransportChannel::FindOldestConnectionNeedingTriggeredCheck( | 1948 Connection* P2PTransportChannel::FindOldestConnectionNeedingTriggeredCheck( |
1884 int64_t now) { | 1949 int64_t now) { |
1885 Connection* oldest_needing_triggered_check = nullptr; | 1950 Connection* oldest_needing_triggered_check = nullptr; |
1886 for (auto conn : connections_) { | 1951 for (auto conn : connections_) { |
1887 if (!IsPingable(conn, now)) { | 1952 if (!IsPingable(conn, now)) { |
1888 continue; | 1953 continue; |
1889 } | 1954 } |
1890 bool needs_triggered_check = | 1955 bool needs_triggered_check = |
1891 (!conn->writable() && | 1956 (!conn->writable() && |
1892 conn->last_ping_received() > conn->last_ping_sent()); | 1957 conn->last_ping_received() > conn->last_ping_sent()); |
1893 if (needs_triggered_check && | 1958 if (needs_triggered_check && |
1894 (!oldest_needing_triggered_check || | 1959 (!oldest_needing_triggered_check || |
1895 (conn->last_ping_received() < | 1960 (conn->last_ping_received() < |
1896 oldest_needing_triggered_check->last_ping_received()))) { | 1961 oldest_needing_triggered_check->last_ping_received()))) { |
1897 oldest_needing_triggered_check = conn; | 1962 oldest_needing_triggered_check = conn; |
1898 } | 1963 } |
1899 } | 1964 } |
1900 | 1965 |
1901 if (oldest_needing_triggered_check) { | 1966 if (oldest_needing_triggered_check) { |
1902 LOG(LS_INFO) << "Selecting connection for triggered check: " | 1967 LOG(LS_INFO) << "Selecting connection for triggered check: " |
1903 << oldest_needing_triggered_check->ToString(); | 1968 << oldest_needing_triggered_check->ToString(); |
1904 } | 1969 } |
1905 return oldest_needing_triggered_check; | 1970 return oldest_needing_triggered_check; |
1906 } | 1971 } |
1907 | 1972 |
1908 Connection* P2PTransportChannel::FindConnectionToPing(int64_t now) { | |
1909 RTC_CHECK(connections_.size() == | |
1910 pinged_connections_.size() + unpinged_connections_.size()); | |
1911 | |
1912 // If there is nothing pingable in the |unpinged_connections_|, copy | |
1913 // over from |pinged_connections_|. We do this here such that the | |
1914 // new connection will take precedence. | |
1915 if (std::find_if(unpinged_connections_.begin(), unpinged_connections_.end(), | |
1916 [this, now](Connection* conn) { | |
1917 return this->IsPingable(conn, now); | |
1918 }) == unpinged_connections_.end()) { | |
1919 unpinged_connections_.insert(pinged_connections_.begin(), | |
1920 pinged_connections_.end()); | |
1921 pinged_connections_.clear(); | |
1922 } | |
1923 | |
1924 Connection* conn_to_ping = FindOldestConnectionNeedingTriggeredCheck(now); | |
1925 if (conn_to_ping) { | |
1926 return conn_to_ping; | |
1927 } | |
1928 | |
1929 for (Connection* conn : unpinged_connections_) { | |
1930 if (!IsPingable(conn, now)) { | |
1931 continue; | |
1932 } | |
1933 if (!conn_to_ping || | |
1934 SelectMostPingableConnection(conn_to_ping, conn) == conn) { | |
1935 conn_to_ping = conn; | |
1936 } | |
1937 } | |
1938 return conn_to_ping; | |
1939 } | |
1940 | |
1941 Connection* P2PTransportChannel::MostLikelyToWork(Connection* conn1, | 1973 Connection* P2PTransportChannel::MostLikelyToWork(Connection* conn1, |
1942 Connection* conn2) { | 1974 Connection* conn2) { |
1943 bool rr1 = IsRelayRelay(conn1); | 1975 bool rr1 = IsRelayRelay(conn1); |
1944 bool rr2 = IsRelayRelay(conn2); | 1976 bool rr2 = IsRelayRelay(conn2); |
1945 if (rr1 && !rr2) { | 1977 if (rr1 && !rr2) { |
1946 return conn1; | 1978 return conn1; |
1947 } else if (rr2 && !rr1) { | 1979 } else if (rr2 && !rr1) { |
1948 return conn2; | 1980 return conn2; |
1949 } else if (rr1 && rr2) { | 1981 } else if (rr1 && rr2) { |
1950 bool udp1 = IsUdp(conn1); | 1982 bool udp1 = IsUdp(conn1); |
(...skipping 11 matching lines...) Expand all Loading... | |
1962 Connection* conn2) { | 1994 Connection* conn2) { |
1963 if (conn1->last_ping_sent() < conn2->last_ping_sent()) { | 1995 if (conn1->last_ping_sent() < conn2->last_ping_sent()) { |
1964 return conn1; | 1996 return conn1; |
1965 } | 1997 } |
1966 if (conn1->last_ping_sent() > conn2->last_ping_sent()) { | 1998 if (conn1->last_ping_sent() > conn2->last_ping_sent()) { |
1967 return conn2; | 1999 return conn2; |
1968 } | 2000 } |
1969 return nullptr; | 2001 return nullptr; |
1970 } | 2002 } |
1971 | 2003 |
1972 Connection* P2PTransportChannel::SelectMostPingableConnection( | 2004 Connection* P2PTransportChannel::MorePingable(Connection* conn1, |
1973 Connection* conn1, | 2005 Connection* conn2) { |
1974 Connection* conn2) { | |
1975 RTC_DCHECK(conn1 != conn2); | 2006 RTC_DCHECK(conn1 != conn2); |
1976 if (config_.prioritize_most_likely_candidate_pairs) { | 2007 if (config_.prioritize_most_likely_candidate_pairs) { |
1977 Connection* most_likely_to_work_conn = MostLikelyToWork(conn1, conn2); | 2008 Connection* most_likely_to_work_conn = MostLikelyToWork(conn1, conn2); |
1978 if (most_likely_to_work_conn) { | 2009 if (most_likely_to_work_conn) { |
1979 return most_likely_to_work_conn; | 2010 return most_likely_to_work_conn; |
1980 } | 2011 } |
1981 } | 2012 } |
1982 | 2013 |
1983 Connection* least_recently_pinged_conn = LeastRecentlyPinged(conn1, conn2); | 2014 Connection* least_recently_pinged_conn = LeastRecentlyPinged(conn1, conn2); |
1984 if (least_recently_pinged_conn) { | 2015 if (least_recently_pinged_conn) { |
1985 return least_recently_pinged_conn; | 2016 return least_recently_pinged_conn; |
1986 } | 2017 } |
1987 | 2018 |
1988 // During the initial state when nothing has been pinged yet, return the first | 2019 // During the initial state when nothing has been pinged yet, return the first |
1989 // one in the ordered |connections_|. | 2020 // one in the ordered |connections_|. |
1990 return *(std::find_if(connections_.begin(), connections_.end(), | 2021 return *(std::find_if(connections_.begin(), connections_.end(), |
1991 [conn1, conn2](Connection* conn) { | 2022 [conn1, conn2](Connection* conn) { |
1992 return conn == conn1 || conn == conn2; | 2023 return conn == conn1 || conn == conn2; |
1993 })); | 2024 })); |
1994 } | 2025 } |
1995 | 2026 |
1996 } // namespace cricket | 2027 } // namespace cricket |
OLD | NEW |