Index: webrtc/p2p/base/p2ptransportchannel.cc |
diff --git a/webrtc/p2p/base/p2ptransportchannel.cc b/webrtc/p2p/base/p2ptransportchannel.cc |
index 3f68d6d6e078fd635e8f696b3b46ae12bae8ce67..25bcebebcebd8f8407611c086986adb5a5df8fca 100644 |
--- a/webrtc/p2p/base/p2ptransportchannel.cc |
+++ b/webrtc/p2p/base/p2ptransportchannel.cc |
@@ -1248,6 +1248,8 @@ void P2PTransportChannel::SortConnectionsAndUpdateState() { |
// have higher priority if it is writable. |
MaybeSwitchSelectedConnection(top_connection, "sorting"); |
+ UpdatePremierConnections(); |
+ |
// The controlled side can prune only if the selected connection has been |
// nominated because otherwise it may prune the connection that will be |
// selected by the controlling side. |
@@ -1285,6 +1287,21 @@ void P2PTransportChannel::SortConnectionsAndUpdateState() { |
MaybeStartPinging(); |
} |
+void P2PTransportChannel::UpdatePremierConnections() { |
+ // |connections_| has been sorted, so the first one in the list on a given |
+ // network is the premier connection, except that the selected connection |
+ // is always the premier connection on the network. |
+ premier_connection_by_network_name_.clear(); |
+ for (Connection* conn : connections_) { |
+ const std::string& network_name = conn->port()->Network()->name(); |
+ if (conn == selected_connection_ || |
+ premier_connection_by_network_name_.find(network_name) == |
+ premier_connection_by_network_name_.end()) { |
+ premier_connection_by_network_name_[network_name] = conn; |
+ } |
+ } |
+} |
+ |
void P2PTransportChannel::PruneConnections() { |
// We can prune any connection for which there is a connected, writable |
// connection on the same network with better or equal priority. We leave |
@@ -1295,25 +1312,16 @@ void P2PTransportChannel::PruneConnections() { |
// switch. If the |premier| connection is not connected, we may be |
// reconnecting a TCP connection and temporarily do not prune connections in |
// this network. See the big comment in CompareConnectionStates. |
- |
- // Get a list of the networks that we are using. |
- std::set<rtc::Network*> networks; |
- for (const Connection* conn : connections_) { |
- networks.insert(conn->port()->Network()); |
- } |
- for (rtc::Network* network : networks) { |
- Connection* premier = GetBestConnectionOnNetwork(network); |
- // Do not prune connections if the current selected connection is weak on |
+ for (Connection* conn : connections_) { |
+ // Do not prune connections if the current premier connection is weak on |
// this network. Otherwise, it may delete connections prematurely. |
- if (!premier || premier->weak()) { |
+ Connection* premier = |
+ premier_connection_by_network_name_[conn->port()->Network()->name()]; |
+ if (!premier || conn == premier || premier->weak()) { |
continue; |
} |
- |
- for (Connection* conn : connections_) { |
- if ((conn != premier) && (conn->port()->Network() == network) && |
- (CompareConnectionCandidates(premier, conn) >= 0)) { |
- conn->Prune(); |
- } |
+ if (CompareConnectionCandidates(premier, conn) >= 0) { |
+ conn->Prune(); |
} |
} |
} |
@@ -1451,26 +1459,6 @@ bool P2PTransportChannel::ReadyToSend(Connection* connection) const { |
PresumedWritable(connection)); |
} |
-// If we have a selected connection, return it, otherwise return top one in the |
-// list (later we will mark it best). |
-Connection* P2PTransportChannel::GetBestConnectionOnNetwork( |
- rtc::Network* network) const { |
- // If the selected connection is on this network, then it wins. |
- if (selected_connection_ && |
- (selected_connection_->port()->Network() == network)) { |
- return selected_connection_; |
- } |
- |
- // Otherwise, we return the top-most in sorted order. |
- for (size_t i = 0; i < connections_.size(); ++i) { |
- if (connections_[i]->port()->Network() == network) { |
- return connections_[i]; |
- } |
- } |
- |
- return NULL; |
-} |
- |
// Handle any queued up requests |
void P2PTransportChannel::OnMessage(rtc::Message *pmsg) { |
switch (pmsg->message_id) { |
@@ -1548,19 +1536,26 @@ bool P2PTransportChannel::IsPingable(const Connection* conn, |
return false; |
} |
- // If the channel is weakly connected, ping all connections. |
- if (weak()) { |
- return true; |
- } |
- |
- // Always ping active connections regardless whether the channel is completed |
- // or not, but backup connections are pinged at a slower rate. |
- if (IsBackupConnection(conn)) { |
+ // Backup connections are pinged at a slower rate if the channel is strongly |
+ // connected. |
+ bool strongly_connected = !weak(); |
+ if (strongly_connected && IsBackupConnection(conn)) { |
return conn->rtt_samples() == 0 || |
(now >= conn->last_ping_response_received() + |
config_.backup_connection_ping_interval); |
} |
- // Don't ping inactive non-backup connections. |
+ |
+ // 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.
|
+ // the same network. Otherwise, do not ping those with a lower priority |
+ // (i.e., those having been pruned) or those which have timed out. |
+ auto iter = |
+ premier_connection_by_network_name_.find(conn->port()->Network()->name()); |
+ if (iter == premier_connection_by_network_name_.end() || !iter->second || |
+ iter->second->weak()) { |
+ return true; |
+ } |
+ |
+ // Don't ping inactive connections. |
if (!conn->active()) { |
return false; |
} |
@@ -1576,14 +1571,41 @@ bool P2PTransportChannel::IsPingable(const Connection* conn, |
return (now >= conn->last_ping_sent() + ping_interval); |
} |
-bool P2PTransportChannel::IsSelectedConnectionPingable(int64_t now) { |
- if (!selected_connection_ || !selected_connection_->connected() || |
- !selected_connection_->writable()) { |
+bool P2PTransportChannel::IsPremierConnectionPingable( |
+ Connection* premier_connection, |
+ int64_t now) { |
+ if (!premier_connection || !premier_connection->connected() || |
+ !premier_connection->writable() || |
+ 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
|
return false; |
} |
- int interval = CalculateActiveWritablePingInterval(selected_connection_, now); |
- return selected_connection_->last_ping_sent() + interval <= now; |
+ int interval = CalculateActiveWritablePingInterval(premier_connection, now); |
+ return premier_connection->last_ping_sent() + interval <= now; |
+} |
+ |
+Connection* P2PTransportChannel::FindBestPremierConnectionToPing(int64_t now) { |
+ // If the selected connection is pingable, select it to ping. |
+ if (IsPremierConnectionPingable(selected_connection_, now)) { |
+ return selected_connection_; |
+ } |
+ |
+ // Otherwise, find the premier connection that has not been pinged for the |
+ // longest time. |
+ Connection* oldest_premier_connection = nullptr; |
+ for (auto kv : premier_connection_by_network_name_) { |
+ Connection* conn = kv.second; |
+ if (conn == nullptr || conn == selected_connection_) { |
+ continue; |
+ } |
+ if (IsPremierConnectionPingable(conn, now) && |
+ (!oldest_premier_connection || |
+ conn->last_ping_sent() < |
+ oldest_premier_connection->last_ping_sent())) { |
+ oldest_premier_connection = conn; |
+ } |
+ } |
+ return oldest_premier_connection; |
} |
int P2PTransportChannel::CalculateActiveWritablePingInterval( |
@@ -1598,8 +1620,9 @@ int P2PTransportChannel::CalculateActiveWritablePingInterval( |
int stable_interval = config_.stable_writable_connection_ping_interval; |
int stablizing_interval = |
std::min(stable_interval, STABILIZING_WRITABLE_CONNECTION_PING_INTERVAL); |
- |
- return conn->stable(now) ? stable_interval : stablizing_interval; |
+ // If the channel is weak or the connection is not stable yet, use the |
+ // stablizing_interval. |
+ 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.
|
} |
// Returns the next pingable connection to ping. This will be the oldest |
@@ -1611,10 +1634,8 @@ int P2PTransportChannel::CalculateActiveWritablePingInterval( |
// CompareConnectionStates. |
Connection* P2PTransportChannel::FindNextPingableConnection() { |
int64_t now = rtc::TimeMillis(); |
- Connection* conn_to_ping = nullptr; |
- if (IsSelectedConnectionPingable(now)) { |
- conn_to_ping = selected_connection_; |
- } else { |
+ Connection* conn_to_ping = FindBestPremierConnectionToPing(now); |
+ if (!conn_to_ping) { |
conn_to_ping = FindConnectionToPing(now); |
} |
return conn_to_ping; |
@@ -1728,9 +1749,16 @@ void P2PTransportChannel::OnConnectionDestroyed(Connection* connection) { |
pinged_connections_.erase(*iter); |
unpinged_connections_.erase(*iter); |
connections_.erase(iter); |
+ for (auto kv : premier_connection_by_network_name_) { |
+ if (kv.second == connection) { |
+ kv.second = nullptr; |
+ } |
+ } |
- LOG_J(LS_INFO, this) << "Removed connection (" |
- << static_cast<int>(connections_.size()) << " remaining)"; |
+ 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
|
+ << std::dec << " (" |
+ << static_cast<int>(connections_.size()) |
+ << " remaining)"; |
// If this is currently the selected connection, then we need to pick a new |
// one. The call to SortConnectionsAndUpdateState will pick a new one. It |
@@ -1858,7 +1886,7 @@ void P2PTransportChannel::OnReadyToSend(Connection* connection) { |
// Find "triggered checks". We ping first those connections that have |
// received a ping but have not sent a ping since receiving it |
-// (last_received_ping > last_sent_ping). But we shouldn't do |
+// (last_ping_received > last_ping_sent). But we shouldn't do |
// triggered checks if the connection is already writable. |
Connection* P2PTransportChannel::FindOldestConnectionNeedingTriggeredCheck( |
int64_t now) { |