internal void TimePassed()
{
// If peer inactivation is disabled, do nothing
if (_owningTorrent.Settings.TimeToWaitUntilIdle.TotalSeconds == 0)
return;
// If we've not reached the maximum peers for this torrent, there's nothing for us to do
if (_owningTorrent.Settings.MaxConnections > _owningTorrent.OpenConnections)
return;
// If there are no available peers, there's nothing for us to do
if (_owningTorrent.Peers.AvailableCount < 0)
return;
// Look for a peer that has not given us any data and that is eligible for being marked inactive
// If we find one that is not interesting, disconnect it straightaway; otherwise disconnect the first interesting one we found
// If there are no eligible peers that have sent us no data, look for peers that have sent data but not for a while
var indexOfFirstUninterestingCandidate = -1; // -1 indicates we haven't found one yet
var indexOfFirstInterestingCandidate = -1;
var leastAttractiveCandidate = -1; // The least attractive peer that has sent us data
var longestCalculatedInactiveTime = 0; // Seconds we calculated for the least attractive candidate
// FIXME These three variables aren't used in the calculation - need to fix this.
var candidateSecondsConnected = 0;
var candidateSecondsSinceLastBlock = -1;
var candidateDataBytes = -1;
for (var i = 0; i < _owningTorrent.Peers.ConnectedPeers.Count; i++)
{
var nextPeer = _owningTorrent.Peers.ConnectedPeers[i];
if (nextPeer.Monitor.DataBytesDownloaded == 0 &&
nextPeer.WhenConnected.Add(_owningTorrent.Settings.TimeToWaitUntilIdle) < DateTime.Now)
{
// This one is eligible for marking as inactive
if (!nextPeer.AmInterested)
{
// This is an eligible peer and we're not interested in it so stop looking
indexOfFirstUninterestingCandidate = i;
candidateSecondsConnected = (int) (DateTime.Now.Subtract(nextPeer.WhenConnected)).TotalSeconds;
candidateSecondsSinceLastBlock = -1;
candidateDataBytes = -1;
break;
}
// This is an eligible peer, but we're interested in it; remember it for potential disconnection if it's the first one we found
if (indexOfFirstInterestingCandidate < 0)
{
indexOfFirstInterestingCandidate = i;
candidateSecondsConnected = (int) (DateTime.Now.Subtract(nextPeer.WhenConnected)).TotalSeconds;
candidateSecondsSinceLastBlock = -1;
candidateDataBytes = -1;
}
}
else
{
// No point looking for inactive peers that have sent us data if we found a candidate that's sent us nothing or if we aren't allowed
// to disconnect peers that have sent us data.
// If the number of available peers is running low (less than max number of peer connections), don't try to inactivate peers that have given us data
if (indexOfFirstInterestingCandidate < 0
&& _owningTorrent.Settings.ConnectionRetentionFactor > 0
&& nextPeer.Monitor.DataBytesDownloaded > 0
&& _owningTorrent.Peers.AvailableCount >= _owningTorrent.Settings.MaxConnections)
{
// Calculate an inactive time.
// Base time is time since the last message (in seconds)
// Give the peer an extra second for every 'ConnectionRetentionFactor' bytes
var timeSinceLastBlock = DateTime.Now.Subtract(nextPeer.LastBlockReceived);
var calculatedInactiveTime =
Convert.ToInt32(timeSinceLastBlock.TotalSeconds -
Convert.ToInt32(nextPeer.Monitor.DataBytesDownloaded/
_owningTorrent.Settings.ConnectionRetentionFactor));
// Register as the least attractive candidate if the calculated time is more than the idle wait time and more than any other candidate
if (calculatedInactiveTime > _owningTorrent.Settings.TimeToWaitUntilIdle.TotalSeconds &&
calculatedInactiveTime > longestCalculatedInactiveTime)
{
longestCalculatedInactiveTime = calculatedInactiveTime;
leastAttractiveCandidate = i;
candidateSecondsConnected =
(int) (DateTime.Now.Subtract(nextPeer.WhenConnected)).TotalSeconds;
candidateSecondsSinceLastBlock =
(int) (DateTime.Now.Subtract(nextPeer.LastBlockReceived)).TotalSeconds;
candidateDataBytes = (int) nextPeer.Monitor.DataBytesDownloaded;
}
}
}
}
// We've finished looking for a disconnect candidate
// Disconnect the uninteresting candidate if found;
// otherwise disconnect the interesting candidate if found;
// otherwise disconnect the least attractive candidate
// otherwise do nothing
var peerToDisconnect = indexOfFirstUninterestingCandidate;
if (peerToDisconnect < 0)
peerToDisconnect = indexOfFirstInterestingCandidate;
if (peerToDisconnect < 0)
peerToDisconnect = leastAttractiveCandidate;
if (peerToDisconnect < 0)
return;
// We've found a peer to disconnect
// Add it to the inactive list for this torrent and disconnect it
_inactivePeerList.Add(_owningTorrent.Peers.ConnectedPeers[peerToDisconnect].Uri);
_owningTorrent.Peers.ConnectedPeers[peerToDisconnect].ConnectionManager.CleanupSocket(
_owningTorrent.Peers.ConnectedPeers[peerToDisconnect], "Marked as inactive");
}