public override void Choke(PeerId id)
        {
            base.Choke(id);

            advertisedPieces.RemoveAll(delegate(SeededPiece p) { return(p.Peer == id); });

            // Place the peer at the end of the list so the rest of the peers
            // will get an opportunity to unchoke before this peer gets tried again
            ChokeData data = peers.Find(delegate(ChokeData d) { return(d.Peer == id); });

            peers.Remove(data);
            peers.Add(data);
        }
        void TryChoke(ChokeData data)
        {
            // Already choked
            if (data.Peer.AmChoking)
            {
                return;
            }

            if (!data.Peer.IsInterested)
            {
                // Choke him if he's not interested
                Choke(data.Peer);
            }
            else if (!advertisedPieces.Exists(delegate(SeededPiece p) { return(p.Peer == data.Peer); }))
            {
                // If we have no free slots and peers are waiting, choke after 30 seconds.
                // FIXME: Choke as soon as the next piece completes *or* a larger time limit *and*
                // at least one piece has uploaded.
                data.LastChoked = DateTime.Now;
                Choke(data.Peer);
            }
        }
        void TryUnchoke(ChokeData data)
        {
            // Already unchoked
            if (!data.Peer.AmChoking)
            {
                return;
            }

            // Don't unchoke if he's not interested
            if (!data.Peer.IsInterested)
            {
                return;
            }

            // Don't unchoke if we are have maxed our slots
            if (manager.UploadingTo >= manager.Settings.UploadSlots)
            {
                return;
            }

            data.LastUnchoked = DateTime.Now;
            Unchoke(data.Peer);
        }
        void TryAdvertisePiece(ChokeData data)
        {
            // If we are seeding to this peer and we have a peer waiting to unchoke
            // don't advertise more data
            if (!data.Peer.AmChoking && PendingUnchoke)
            {
                return;
            }

            int advertised = advertisedPieces.FindAll(delegate(SeededPiece p) { return(p.Peer == data.Peer); }).Count;
            int max = MaxAdvertised;

            if (manager.UploadingTo < manager.Settings.UploadSlots)
            {
                max = MaxAdvertised;
            }
            else if (data.ShareRatio < 0.25)
            {
                max = 1;
            }
            else if (data.ShareRatio < 0.35)
            {
                max = 2;
            }
            else if (data.ShareRatio < 0.50)
            {
                max = 3;
            }
            else
            {
                max = MaxAdvertised;
            }

            if (advertised >= max)
            {
                return;
            }

            // List of pieces *not* in the swarm
            temp.From(bitfield).Not();

            // List of pieces that he wants that aren't in the swarm
            temp.NAnd(data.Peer.BitField);

            // Ignore all the pieces we've already started sharing
            foreach (SeededPiece p in advertisedPieces)
            {
                temp[p.Index] = false;
            }

            int index = 0;

            while (advertised < max)
            {
                // Get the index of the first piece we can send him
                index = temp.FirstTrue(index, temp.Length);
                // Looks like he's not interested in us...
                if (index == -1)
                {
                    return;
                }

                advertised++;
                data.TotalPieces++;
                data.CurrentPieces[index] = true;
                advertisedPieces.Add(new SeededPiece(data.Peer, index, data.Peer.TorrentManager.Torrent.PieceLength / Piece.BlockSize));
                data.Peer.Enqueue(new HaveMessage(index));
                index++;
            }
        }