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

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

Issue 2369963004: Ping the premier connection on each network with higher priority. (Closed)
Patch Set: Rearrange FindNextPingableConnection Created 4 years, 1 month 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
« no previous file with comments | « webrtc/p2p/base/p2ptransportchannel.h ('k') | webrtc/p2p/base/p2ptransportchannel_unittest.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
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 48 matching lines...) Expand 10 before | Expand all | Expand 10 after
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
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
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
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
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
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
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
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
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
OLDNEW
« no previous file with comments | « webrtc/p2p/base/p2ptransportchannel.h ('k') | webrtc/p2p/base/p2ptransportchannel_unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698