public void TimePassed()
{
//Start by identifying:
// the choked and interested peers
// the number of unchoked peers
//Choke peers that have become disinterested at the same time
var chokedInterestedPeers = new List<PeerId>();
var interestedCount = 0;
var unchokedCount = 0;
var skipDownload = (_isDownloading &&
(_owningTorrent.Monitor.DownloadSpeed <
(_owningTorrent.Settings.MaxDownloadSpeed*_percentOfMaxRateToSkipReview/100.0)));
var skipUpload = (!_isDownloading &&
(_owningTorrent.Monitor.UploadSpeed <
(_owningTorrent.Settings.MaxUploadSpeed*_percentOfMaxRateToSkipReview/100.0)));
skipDownload = skipDownload && _owningTorrent.Settings.MaxDownloadSpeed > 0;
skipUpload = skipUpload && _owningTorrent.Settings.MaxUploadSpeed > 0;
foreach (var connectedPeer in _owningTorrent.Peers.ConnectedPeers)
{
if (connectedPeer.Connection == null)
continue;
//If the peer is a seeder and we are not currently interested in it, put that right
if (connectedPeer.Peer.IsSeeder && !connectedPeer.AmInterested)
{
// FIXME - Is this necessary anymore? I don't think so
//owningTorrent.Mode.SetAmInterestedStatus(connectedPeer, true);
//Send2Log("Forced AmInterested: " + connectedPeer.Peer.Location);
}
// If the peer is interesting try to queue up some piece requests off him
// If he is choking, we will only queue a piece if there is a FastPiece we can choose
if (connectedPeer.AmInterested)
_owningTorrent.PieceManager.AddPieceRequests(connectedPeer);
if (connectedPeer.Peer.IsSeeder)
continue;
if (!connectedPeer.IsInterested && !connectedPeer.AmChoking)
//This peer is disinterested and unchoked; choke it
Choke(connectedPeer);
else if (connectedPeer.IsInterested)
{
interestedCount++;
if (!connectedPeer.AmChoking) //This peer is interested and unchoked, count it
unchokedCount++;
else
chokedInterestedPeers.Add(connectedPeer);
//This peer is interested and choked, remember it and count it
}
}
if (_firstCall)
{
//This is the first time we've been called for this torrent; set current status and run an initial review
_isDownloading = !_owningTorrent.Complete; //If progress is less than 100% we must be downloading
_firstCall = false;
ExecuteReview();
}
else if (_isDownloading && _owningTorrent.Complete)
{
//The state has changed from downloading to seeding; set new status and run an initial review
_isDownloading = false;
ExecuteReview();
}
else if (interestedCount <= _owningTorrent.Settings.UploadSlots)
//Since we have enough slots to satisfy everyone that's interested, unchoke them all; no review needed
UnchokePeerList(chokedInterestedPeers);
else if (_minimumTimeBetweenReviews > 0 &&
(SecondsBetween(_timeOfLastReview, DateTime.Now) >= _minimumTimeBetweenReviews) &&
(skipDownload || skipUpload))
//Based on the time of the last review, a new review is due
//There are more interested peers than available upload slots
//If we're downloading, the download rate is insufficient to skip the review
//If we're seeding, the upload rate is insufficient to skip the review
//So, we need a review
ExecuteReview();
else
//We're not going to do a review this time
//Allocate any available slots based on the results of the last review
AllocateSlots(unchokedCount);
}