private void DoTorrentDownload(TorrentData info)
        {
            System.Windows.Application.Current.Dispatcher.BeginInvoke((Action) delegate
            {
                PlayButton.IsEnabled  = false;
                CheckButton.IsEnabled = false;

                StatusText.Visibility = Visibility.Visible;
                StatusText.Text       = LanguageMgr.Instance.ValueOf("StatusText_Download");

                if (info.DownloadSpeed.Split(' ')[0] != "0")
                {
                    StatusTextDesc.Text  = $"{string.Format(LanguageMgr.Instance.ValueOf("Download_Speed_Title"), info.DownloadSpeed)}";
                    StatusTextDesc.Text += $" {string.Format(LanguageMgr.Instance.ValueOf("Download_Speed_Downloaded"), info.TotalRead)}";
                    PercentStatus.Text   = $"{info.Progress}%";
                }
                else
                {
                    StatusTextDesc.Text = LanguageMgr.Instance.ValueOf("StatusText_GamePrepare");
                    PercentStatus.Text  = $"{info.Progress}%";
                }

                PercentStatus.Visibility = Visibility.Visible;
                ProgressBar.Visibility   = Visibility.Visible;
                ProgressBar.Value        = info.Progress;

                WindowMgr.Instance.Run <MainWindow>((window) =>
                {
                    window.SwitchMenuButtons(false);
                });
            });
        }
        IList <BlockInfo> GetStandardRequest(IPeer peer, BitField current, int startIndex, int endIndex, int count)
        {
            int piecesNeeded = (count * Piece.BlockSize) / TorrentData.PieceLength;

            if ((count * Piece.BlockSize) % TorrentData.PieceLength != 0)
            {
                piecesNeeded++;
            }
            int checkIndex = CanRequest(current, startIndex, endIndex, ref piecesNeeded);

            // Nothing to request.
            if (checkIndex == -1)
            {
                return(null);
            }

            var bundle = new List <BlockInfo> (count);

            for (int i = 0; bundle.Count < count && i < piecesNeeded; i++)
            {
                // Request the piece
                var p = new Piece(checkIndex + i, TorrentData.BytesPerPiece(checkIndex + i));
                requests.Add(p);
                for (int j = 0; j < p.Blocks.Length && bundle.Count < count; j++)
                {
                    bundle.Add(p.Blocks[j].CreateRequest(peer));
                }
            }
            return(bundle);
        }
Beispiel #3
0
        public string Get(TorrentData request)
        {
            UpdateTorrentList();

            var totalDownloadRate = FileSizeConversions.SizeSuffix(Torrents.Sum(t => Convert.ToInt32(t.DownloadSpeed))).Split(' ');
            var totalUploadRate   = FileSizeConversions.SizeSuffix(Torrents.Sum(t => Convert.ToInt32(t.UploadSpeed))).Split(' ');
            var totalRecordCount  = Torrents.Count;

            //if (request.StartIndex != null)
            //{
            //    Torrents = Torrents.GetRange(request.StartIndex.Value, 20);
            //}

            switch (request.SortBy)
            {
            case "DateAdded": Torrents = Torrents.OrderBy(t => DateTime.Parse(t.AddedDate)).Reverse().ToList(); break;

            case "Name": Torrents = Torrents.OrderBy(t => t.Name).ToList(); break;

            case "FileSize": Torrents = Torrents.OrderBy(t => Convert.ToInt64(t.TotalBytes)).Reverse().ToList(); break;
            }

            return(JsonSerializer.SerializeToString(new TorrentData()
            {
                torrents = Torrents,
                TotalRecordCount = totalRecordCount,
                sizeDownload = totalDownloadRate[0],
                sizeSuffixDownload = totalDownloadRate[1],
                sizeUpload = totalUploadRate[0],
                sizeSuffixUpload = totalUploadRate[1],
                sizeTotalDriveSpace = FileSizeConversions.SizeSuffix(Torrents.Sum(t => Convert.ToInt64(t.TotalBytes))),
                sizeTotalDriveSpaceBytes = Torrents.Sum(t => Convert.ToInt64(t.TotalBytes)).ToString()
            }));
        }
 public TreeViewForm(TorrentData data)
 {
     _data = data;
     InitializeComponent();
     AddCommand();
     Icon = Icon.ExtractAssociatedIcon(Application.ExecutablePath);
 }
        BlockInfo?GetFromList(IPeer peer, BitField bitfield, IList <int> pieces)
        {
            if (!peer.SupportsFastPeer || !ClientEngine.SupportsFastPeer)
            {
                return(null);
            }

            for (int i = 0; i < pieces.Count; i++)
            {
                int index = pieces[i];
                // A peer should only suggest a piece he has, but just in case.
                if (index >= bitfield.Length || !bitfield[index] || AlreadyRequested(index))
                {
                    continue;
                }

                pieces.RemoveAt(i);
                var p = new Piece(index, TorrentData.BytesPerPiece(index));
                requests.Add(p);
                return(p.Blocks[0].CreateRequest(peer));
            }


            return(null);
        }
        public async Task WriteSameBlockDifferentTorrents()
        {
            var data1 = new byte[] { 1, 1, 1 };
            var data2 = new byte[] { 2, 2, 2 };

            var torrent2 = new TorrentData {
                Files       = torrent.Files,
                PieceLength = torrent.PieceLength,
                Size        = torrent.Size
            };

            var memory = new MemoryCache(new MemoryPool(), 1024, new NullWriter());
            await memory.WriteAsync(torrent, new BlockInfo (0, 0, 3), data1, false);

            await memory.WriteAsync(torrent2, new BlockInfo (0, 0, 3), data2, false);

            var readBuffer = new byte[3];
            await memory.ReadAsync(torrent, new BlockInfo (0, 0, 3), readBuffer);

            CollectionAssert.AreEqual(data1, readBuffer);

            await memory.ReadAsync(torrent2, new BlockInfo (0, 0, 3), readBuffer);

            CollectionAssert.AreEqual(data2, readBuffer);
        }
Beispiel #7
0
        public void TestNonUTF8Encode()
        {
            const string torrentPath = @"..\..\[Torrent Sample]\GBK.torrent";

            _torrent = new TorrentData(torrentPath);
            Assert.AreEqual("[2DJGAME] [2010.03.10] 映画「時をかける少女」主題歌「ノスタルシ゛ア」&挿入歌「時をかける少女」(320k+cover).rar",
                            _torrent.TorrentName);
        }
Beispiel #8
0
 #pragma warning disable CS1591 // Missing XML comment for publicly visible type or member
 public Torrent(BitSwarm bitSwarm)
 {
     this.bitSwarm = bitSwarm;
     file          = new TorrentFile();
     data          = new TorrentData();
     metadata      = new MetaData();
     file.trackers = new List <Uri>();
 }
Beispiel #9
0
                public PieceProgress(ref TorrentData data, int piece)
                {
                    bool isLastPiece = piece == data.pieces - 1 && data.totalSize % data.pieceSize != 0;

                    this.piece    = piece;
                    this.data     = !isLastPiece ? new byte[data.pieceSize] : new byte[data.pieceLastSize];
                    this.progress = !isLastPiece ? new Bitfield(data.blocks): new Bitfield(data.blocksLastPiece);
                    this.requests = !isLastPiece ? new Bitfield(data.blocks): new Bitfield(data.blocksLastPiece);
                }
Beispiel #10
0
        public void TestLoadTorrent4()
        {
            const string torrentPath = @"..\..\[Torrent Sample]\USO.torrent";

            _torrent = new TorrentData(torrentPath);
            PrintTorrentInfo();
            var fileList = _torrent.GetFileList();

            Assert.IsTrue(fileList.Keys.Sum(category => fileList[category].Count(item => item.State == FileState.InValidFile)) == 33);
        }
Beispiel #11
0
        public async Task AddTorrent(Torrent torrent)
        {
            var found = collection.Find(f => f.TorrentId == torrent.TorrentId).Limit(1).Any();

            if (!found)
            {
                var td = new TorrentData(torrent);
                await collection.InsertOneAsync(td);
            }
        }
Beispiel #12
0
        public void TestLoadTorrent6()
        {
            const string torrentPath = @"..\..\[Torrent Sample]\Padding_file.torrent";

            _torrent = new TorrentData(torrentPath);
            PrintTorrentInfo();
            var fileList = _torrent.GetFileList();

            Assert.IsTrue(fileList["root"].Count == 12);
        }
        public void AddRequests(IPeerWithMessaging peer, IReadOnlyList <IPeerWithMessaging> allPeers)
        {
            // The first two pieces in the high priority set should be requested multiple times to ensure fast delivery
            var pieceCount = TorrentData.PieceCount();

            for (int i = HighPriorityPieceIndex; i < pieceCount && i <= HighPriorityPieceIndex + 1; i++)
            {
                AddRequests(peer, allPeers, HighPriorityPieceIndex, HighPriorityPieceIndex, 2);
            }

            var lowPriorityEnd = Math.Min(pieceCount - 1, HighPriorityPieceIndex + LowPriorityCount - 1);

            AddRequests(peer, allPeers, HighPriorityPieceIndex, lowPriorityEnd, 1);
        }
        public void Setup()
        {
            blocksPerPiece = 4;
            pieceCount     = 40;

            bitfield = new BitField(pieceCount);
            data     = new TorrentData {
                PieceLength = Piece.BlockSize * blocksPerPiece,
                Files       = new[] { new TorrentFile("Test", Piece.BlockSize * blocksPerPiece * pieceCount, 0, pieceCount - 1) },
                Size        = Piece.BlockSize * blocksPerPiece * pieceCount - 10
            };

            peer = PeerId.CreateNull(pieceCount, seeder: true, isChoking: false, amInterested: true);
        }
Beispiel #15
0
        public StandardPickerBenchmark()
        {
            Data      = new TorrentData();
            Picker    = new StandardPicker();
            Requester = Data.CreatePeer();
            Requested = new Queue <BlockInfo> ((int)(Data.TorrentInfo.PieceCount() * Data.TorrentInfo.BlocksPerPiece(0)));


            Random          = new Random(1234);
            Requesters      = new List <IPeer> (Enumerable.Range(0, 60).Select(t => Data.CreatePeer()));
            RequestedBlocks = new List <Queue <BlockInfo> > ();
            foreach (var requester in Requesters)
            {
                RequestedBlocks.Add(new Queue <BlockInfo> (1400));
            }
        }
        public void Initialise(ITorrentManagerInfo torrentData, IReadOnlyList <ReadOnlyBitField> ignoringBitfields)
        {
            TorrentData       = torrentData.TorrentInfo !;
            IgnoringBitfields = ignoringBitfields;
            Temp = new BitField(TorrentData.PieceCount());

            var standardPicker = new StandardPicker();

            HighPriorityPicker = IgnoringPicker.Wrap(new PriorityPicker(standardPicker), ignoringBitfields);

            LowPriorityPicker = new RandomisedPicker(standardPicker);
            LowPriorityPicker = new RarestFirstPicker(LowPriorityPicker);
            LowPriorityPicker = new PriorityPicker(LowPriorityPicker);
            LowPriorityPicker = IgnoringPicker.Wrap(LowPriorityPicker, ignoringBitfields);

            LowPriorityPicker.Initialise(torrentData);
            HighPriorityPicker.Initialise(torrentData);
        }
Beispiel #17
0
        public void TestLoadTorrent2()
        {
            const string torrentPath = @"..\..\[Torrent Sample]\SingleFile.torrent";

            _torrent = new TorrentData(torrentPath);
            PrintTorrentInfo();
            Assert.IsTrue(_torrent.GetAnnounceList().First() == "http://tracker.dmhy.org/announce?secure=securecode");
            Assert.IsTrue(string.IsNullOrEmpty(_torrent.Comment));
            Assert.IsTrue(_torrent.CreatedBy == "uTorrent/3220");
            Assert.IsTrue(_torrent.CreationDate == (new DateTime(1970, 1, 1, 0, 0, 0, DateTimeKind.Utc).AddSeconds(1414723640)).Add(TimeZone.CurrentTimeZone.GetUtcOffset(DateTime.Now)));
            Assert.IsTrue(_torrent.IsPrivate);
            Assert.IsTrue(_torrent.Source == "[u2.dmhy.org] U2分享園@動漫花園");
            Assert.IsTrue(_torrent.TorrentName == "[FLsnow][Tamako_love_story][MOVIE][外挂结构].rar");
            var fileList = _torrent.GetFileList();

            Assert.IsTrue(fileList.Count == 1);
            Assert.IsTrue(fileList["single"].Count == 1);
            Assert.IsTrue(fileList.Keys.Sum(category => fileList[category].Count(item => item.State == FileState.InValidFile)) == 0);
        }
Beispiel #18
0
        public void TestLoadTorrent3()
        {
            const string torrentPath = @"..\..\[Torrent Sample]\Martian.torrent";

            _torrent = new TorrentData(torrentPath);
            PrintTorrentInfo();
            Assert.IsTrue(_torrent.GetAnnounceList().First() == "http://tracker.hdtime.org/announce.php?passkey=passkey");
            Assert.IsTrue(string.IsNullOrEmpty(_torrent.Comment));
            Assert.IsTrue(_torrent.CreatedBy == null);
            Assert.IsTrue(_torrent.CreationDate == new DateTime(1970, 1, 1, 0, 0, 0, DateTimeKind.Utc).Add(TimeZone.CurrentTimeZone.GetUtcOffset(DateTime.Now)));
            Assert.IsFalse(_torrent.IsPrivate);
            Assert.IsTrue(_torrent.Source == "[hdtime.org] HDTIME");
            Assert.IsTrue(_torrent.TorrentName == "The Martian 2015 HD-VOD HC x264 AC3-CPG");
            var fileList = _torrent.GetFileList();

            Assert.IsTrue(fileList.Count == 1);
            Assert.IsTrue(fileList["root"].Count == 2);
            Assert.IsTrue(fileList.Keys.Sum(category => fileList[category].Count(item => item.State == FileState.InValidFile)) == 2);
        }
Beispiel #19
0
        public void TestLoadTorrent1()
        {
            const string torrentPath = @"..\..\[Torrent Sample]\Comment.torrent";

            _torrent = new TorrentData(torrentPath);
            PrintTorrentInfo();
            Assert.IsTrue(_torrent.GetAnnounceList().First() == "http://tracker.dmhy.org/announce?secure=securecode");
            Assert.IsTrue(_torrent.Comment == "Ripped And Scanned By imi415@U2");
            Assert.IsTrue(_torrent.CreatedBy == "uTorrent/3.4.2");
            Assert.IsTrue(_torrent.CreationDate == (new DateTime(1970, 1, 1, 0, 0, 0, DateTimeKind.Utc).AddSeconds(1415247690)).Add(TimeZone.CurrentTimeZone.GetUtcOffset(DateTime.Now)));
            Assert.IsTrue(_torrent.IsPrivate);
            Assert.IsTrue(_torrent.Source == "[u2.dmhy.org] U2分享園@動漫花園");
            Assert.IsTrue(_torrent.TorrentName == "南條愛乃 - あなたの愛した世界");
            var fileList = _torrent.GetFileList();

            Assert.IsTrue(fileList.Count == 2);
            Assert.IsTrue(fileList["root"].Count == 4);
            Assert.IsTrue(fileList["スキャン"].Count == 12);
            Assert.IsTrue(fileList.Keys.Sum(category => fileList[category].Count(item => item.State == FileState.InValidFile)) == 14);
        }
        private void TorrentReceived(TorrentInfo ti)
        {
            TorrentData td = new TorrentData(ti);
            int         i;

            lock (torrents)
            {
                for (i = 0; i < torrents.Count; i++)
                {
                    if (torrents[i].EqualsTorrent(td))
                    {
                        torrents[i].Update(td);
                        break;
                    }
                }
                if (i == torrents.Count)
                {
                    AddTorrent(td);
                }
            }
        }
        public void PickHighestPriority()
        {
            var data             = new TorrentData();
            var ignoringBitfield = new MutableBitField(data.PieceCount())
                                   .SetAll(false);

            var requester = new StreamingPieceRequester();

            requester.Initialise(data, new[] { ignoringBitfield });
            requester.SeekToPosition(data.Files[0], data.PieceLength * 3);

            var peer = PeerId.CreateNull(ignoringBitfield.Length, true, false, true);

            requester.AddRequests(peer, Array.Empty <IPeerWithMessaging> ());
            Assert.AreEqual(4, peer.AmRequestingPiecesCount);

            var requests = GetRequests(peer);

            Assert.AreEqual(4, requests.Count);
            Assert.IsTrue(requests.All(r => r.PieceIndex == 3));
        }
Beispiel #22
0
        BlockInfo?ContinueExistingRequest(IPeer peer, int startIndex, int endIndex, int maxDuplicateRequests, bool allowAbandoned, bool allowAny)
        {
            for (int req = 0; req < requests.Count; req++)
            {
                Piece p     = requests[req];
                int   index = p.Index;
                if (p.AllBlocksRequested || index < startIndex || index > endIndex || !peer.BitField[index])
                {
                    continue;
                }

                // For each piece that was assigned to this peer, try to request a block from it
                // A piece is 'assigned' to a peer if he is the first person to request a block from that piece
                if (allowAny || (allowAbandoned && p.Abandoned) || peer == p.Blocks[0].RequestedOff)
                {
                    for (int i = 0; i < p.BlockCount; i++)
                    {
                        if (!p.Blocks[i].Received && !p.Blocks[i].Requested)
                        {
                            return(p.Blocks[i].CreateRequest(peer));
                        }
                    }
                }
            }

            // If all blocks have been requested at least once and we're allowed more than 1 request then
            // let's try and issue a duplicate!
            for (int duplicate = 1; duplicate < maxDuplicateRequests; duplicate++)
            {
                for (int req = 0; req < requests.Count; req++)
                {
                    Piece primaryPiece = requests[req];
                    if (primaryPiece.Index < startIndex || primaryPiece.Index > endIndex || !peer.BitField[primaryPiece.Index])
                    {
                        continue;
                    }

                    if (!duplicates.TryGetValue(primaryPiece.Index, out List <Piece> extraPieces))
                    {
                        duplicates[primaryPiece.Index] = extraPieces = new List <Piece> ();
                    }

                    if (extraPieces.Count < duplicate)
                    {
                        var newPiece = new Piece(primaryPiece.Index, TorrentData.BytesPerPiece(primaryPiece.Index));
                        for (int i = 0; i < primaryPiece.BlockCount; i++)
                        {
                            if (primaryPiece.Blocks[i].Received)
                            {
                                newPiece.Blocks[i].TrySetReceived(primaryPiece.Blocks[i].RequestedOff);
                            }
                        }
                        extraPieces.Add(newPiece);
                    }

                    for (int extraPieceIndex = 0; extraPieceIndex < extraPieces.Count; extraPieceIndex++)
                    {
                        var extraPiece = extraPieces[extraPieceIndex];
                        for (int i = 0; i < extraPiece.BlockCount; i++)
                        {
                            if (!extraPiece.Blocks[i].Requested && !HasAlreadyRequestedBlock(primaryPiece, extraPieces, peer, i))
                            {
                                return(extraPiece.Blocks[i].CreateRequest(peer));
                            }
                        }
                    }
                }
            }

            // If we get here it means all the blocks in the pieces being downloaded by the peer are already requested
            return(null);
        }
 public void AddTorrent(TorrentData torrent)
 {
     torrents.Add(torrent);
 }
 /// <summary>
 /// Inform the picker that we have sequentially read data and so will need to update the high priority set without
 /// cancelling pending requests.
 /// </summary>
 /// <param name="file"></param>
 /// <param name="position"></param>
 public void ReadToPosition(ITorrentFileInfo file, long position)
 {
     HighPriorityPieceIndex = Math.Min(file.EndPieceIndex, TorrentData.ByteOffsetToPieceIndex(position + file.OffsetInTorrent));
 }
        void AddRequests(IPeerWithMessaging peer, IReadOnlyList <IPeerWithMessaging> allPeers, BitField bitfield, int startPieceIndex, int endPieceIndex, int maxDuplicates, int?preferredMaxRequests = null)
        {
            if (!peer.CanRequestMorePieces)
            {
                return;
            }

            int preferredRequestAmount = peer.PreferredRequestAmount(TorrentData.PieceLength);
            var maxRequests            = Math.Min(preferredMaxRequests ?? 3, peer.MaxPendingRequests);

            if (peer.AmRequestingPiecesCount >= maxRequests)
            {
                return;
            }

            // FIXME: Add a test to ensure we do not unintentionally request blocks off peers which are choking us.
            // This used to say if (!peer.IsChoing || peer.SupportsFastPeer), and with the recent changes we might
            // not actually guarantee that 'ContinueExistingRequest' or 'ContinueAnyExistingRequest' properly takes
            // into account that a peer which is choking us can *only* resume a 'fast piece' in the 'AmAllowedfastPiece' list.
            if (!peer.IsChoking)
            {
                while (peer.AmRequestingPiecesCount < maxRequests)
                {
                    BlockInfo?request = Picker.ContinueAnyExistingRequest(peer, startPieceIndex, endPieceIndex, maxDuplicates);
                    if (request != null)
                    {
                        peer.EnqueueRequest(request.Value);
                    }
                    else
                    {
                        break;
                    }
                }
            }

            // If the peer supports fast peer and they are choking us, they'll still send pieces in the allowed fast set.
            if (peer.SupportsFastPeer && peer.IsChoking)
            {
                while (peer.AmRequestingPiecesCount < maxRequests)
                {
                    BlockInfo?request = Picker.ContinueExistingRequest(peer, startPieceIndex, endPieceIndex);
                    if (request != null)
                    {
                        peer.EnqueueRequest(request.Value);
                    }
                    else
                    {
                        break;
                    }
                }
            }

            // Should/could we simplify things for IPiecePicker implementations by guaranteeing IPiecePicker.PickPiece calls will
            // only be made to pieces which *can* be requested? Why not!
            // FIXME add a test for this.
            if (!peer.IsChoking || (peer.SupportsFastPeer && peer.IsAllowedFastPieces.Count > 0))
            {
                while (peer.AmRequestingPiecesCount < maxRequests)
                {
                    IList <BlockInfo> request = PriorityPick(peer, peer.BitField, allPeers, preferredRequestAmount, 0, TorrentData.PieceCount() - 1);
                    if (request != null && request.Count > 0)
                    {
                        peer.EnqueueRequests(request);
                    }
                    else
                    {
                        break;
                    }
                }
            }

            if (!peer.IsChoking && peer.AmRequestingPiecesCount == 0)
            {
                while (peer.AmRequestingPiecesCount < maxRequests)
                {
                    BlockInfo?request = Picker.ContinueAnyExistingRequest(peer, HighPriorityPieceIndex, bitfield.Length - 1, 1);
                    // If this peer is a seeder and we are unable to request any new blocks, then we should enter
                    // endgame mode. Every block has been requested at least once at this point.
                    if (request == null && (InEndgameMode || peer.IsSeeder))
                    {
                        request = Picker.ContinueAnyExistingRequest(peer, 0, TorrentData.PieceCount() - 1, 2);
                        // FIXME: What if the picker is choosing to not allocate pieces? Then it's not endgame mode.
                        // This should be deterministic, not a heuristic?
                        InEndgameMode |= request != null && (bitfield.Length - bitfield.TrueCount) < 10;
                    }

                    if (request != null)
                    {
                        peer.EnqueueRequest(request.Value);
                    }
                    else
                    {
                        break;
                    }
                }
            }
        }
        public void AddRequests(IPeerWithMessaging peer, IReadOnlyList <IPeerWithMessaging> allPeers)
        {
            int maxRequests = peer.MaxPendingRequests;

            if (!peer.CanRequestMorePieces)
            {
                return;
            }

            // This is safe to invoke. 'ContinueExistingRequest' strongly guarantees that a peer will only
            // continue a piece they have initiated. If they're choking then the only piece they can continue
            // will be a fast piece (if one exists!)
            if (!peer.IsChoking || peer.SupportsFastPeer)
            {
                while (peer.AmRequestingPiecesCount < maxRequests)
                {
                    BlockInfo?request = Picker.ContinueExistingRequest(peer, 0, peer.BitField.Length - 1);
                    if (request != null)
                    {
                        peer.EnqueueRequest(request.Value);
                    }
                    else
                    {
                        break;
                    }
                }
            }

            int count = peer.PreferredRequestAmount(TorrentData.PieceLength);

            if (RequestBufferCache.Length < count)
            {
                RequestBufferCache = new Memory <BlockInfo> (new BlockInfo[count]);
            }

            // Reuse the same buffer across multiple requests. However ensure the piecepicker is given
            // a Span<T> of the expected size - so slice the reused buffer if it's too large.
            var requestBuffer = RequestBufferCache.Span.Slice(0, count);

            if (!peer.IsChoking || (peer.SupportsFastPeer && peer.IsAllowedFastPieces.Count > 0))
            {
                BitField filtered = null;
                while (peer.AmRequestingPiecesCount < maxRequests)
                {
                    filtered ??= ApplyIgnorables(peer.BitField);
                    int requests = Picker.PickPiece(peer, filtered, allPeers, 0, TorrentData.PieceCount() - 1, requestBuffer);
                    if (requests > 0)
                    {
                        peer.EnqueueRequests(requestBuffer.Slice(0, requests));
                    }
                    else
                    {
                        break;
                    }
                }
            }

            if (!peer.IsChoking && peer.AmRequestingPiecesCount == 0)
            {
                while (peer.AmRequestingPiecesCount < maxRequests)
                {
                    BlockInfo?request = Picker.ContinueAnyExistingRequest(peer, 0, TorrentData.PieceCount() - 1, 1);
                    // If this peer is a seeder and we are unable to request any new blocks, then we should enter
                    // endgame mode. Every block has been requested at least once at this point.
                    if (request == null && (InEndgameMode || peer.IsSeeder))
                    {
                        request        = Picker.ContinueAnyExistingRequest(peer, 0, TorrentData.PieceCount() - 1, 2);
                        InEndgameMode |= request != null;
                    }

                    if (request != null)
                    {
                        peer.EnqueueRequest(request.Value);
                    }
                    else
                    {
                        break;
                    }
                }
            }
        }
        public void AddRequests(IPeerWithMessaging peer, IReadOnlyList <IPeerWithMessaging> allPeers)
        {
            int maxRequests = peer.MaxPendingRequests;

            if (!peer.CanRequestMorePieces)
            {
                return;
            }

            int count = peer.PreferredRequestAmount(TorrentData.PieceLength);

            // This is safe to invoke. 'ContinueExistingRequest' strongly guarantees that a peer will only
            // continue a piece they have initiated. If they're choking then the only piece they can continue
            // will be a fast piece (if one exists!)
            if (!peer.IsChoking || peer.SupportsFastPeer)
            {
                while (peer.AmRequestingPiecesCount < maxRequests)
                {
                    BlockInfo?request = Picker.ContinueExistingRequest(peer, 0, peer.BitField.Length - 1);
                    if (request != null)
                    {
                        peer.EnqueueRequest(request.Value);
                    }
                    else
                    {
                        break;
                    }
                }
            }

            // FIXME: Would it be easier if RequestManager called PickPiece(AllowedFastPieces[0]) or something along those lines?
            if (!peer.IsChoking || (peer.SupportsFastPeer && peer.IsAllowedFastPieces.Count > 0))
            {
                BitField filtered = null;
                while (peer.AmRequestingPiecesCount < maxRequests)
                {
                    filtered ??= ApplyIgnorables(peer.BitField);
                    IList <BlockInfo> request = Picker.PickPiece(peer, filtered, allPeers, count, 0, TorrentData.PieceCount() - 1);
                    if (request != null && request.Count > 0)
                    {
                        peer.EnqueueRequests(request);
                    }
                    else
                    {
                        break;
                    }
                }
            }

            if (!peer.IsChoking && peer.AmRequestingPiecesCount == 0)
            {
                while (peer.AmRequestingPiecesCount < maxRequests)
                {
                    BlockInfo?request = Picker.ContinueAnyExistingRequest(peer, 0, TorrentData.PieceCount() - 1, 1);
                    // If this peer is a seeder and we are unable to request any new blocks, then we should enter
                    // endgame mode. Every block has been requested at least once at this point.
                    if (request == null && (InEndgameMode || peer.IsSeeder))
                    {
                        request        = Picker.ContinueAnyExistingRequest(peer, 0, TorrentData.PieceCount() - 1, 2);
                        InEndgameMode |= request != null;
                    }

                    if (request != null)
                    {
                        peer.EnqueueRequest(request.Value);
                    }
                    else
                    {
                        break;
                    }
                }
            }
        }
Beispiel #28
0
        /// <summary>
        /// Handles every button from the last Columns of the DataGrid, on button click event it reads from the selected row:
        /// magnet link, actual_client, clientType
        /// Sends the magnet link to the right client.
        /// </summary>
        /// <param name="sender">The source of the event.</param>
        /// <param name="e">The <see cref="RoutedEventArgs"/> instance containing the event data.</param>
        public async void sendTorrent(object sender, RoutedEventArgs e)
        {
            TorrentData TorrentDataFromRow = (TorrentData)dataGrid.SelectedItems[0];

            string actualClient = dataGrid.CurrentColumn.Header.ToString();
            string magnet       = TorrentDataFromRow.Magnet;

            Settings   clientSettings = client.GetByAlias(actualClient);
            ClientType currentType    = clientSettings.ManagerClientType;

            switch (currentType)
            {
            case ClientType.uTorrent:
                if (await Task.Run(() => uTorrent.SendMagnetURI(clientSettings, magnet)))
                {
                    dataGrid.Items.RemoveAt(dataGrid.SelectedIndex);
                }
                else
                {
                }
                break;

            case ClientType.Deluge:
                if (await Task.Run(() => deluge.SendMagnetURI(clientSettings, magnet)))
                {
                    dataGrid.RowBackground = Brushes.Yellow;
                    dataGrid.Items.RemoveAt(dataGrid.SelectedIndex);
                }
                else
                {
                    //change color to red
                }
                break;

            case ClientType.Transmission:
                if (await Task.Run(() => transmission.SendMagnetURI(clientSettings, magnet)))
                {
                    dataGrid.Items.RemoveAt(dataGrid.SelectedIndex);
                }
                else
                {
                    //change color to red
                }
                break;

            case ClientType.Qbittorrent:
                if (await Task.Run(() => managers.Qbittorrent.SendMagnetURI(clientSettings, magnet)))
                {
                    dataGrid.Items.RemoveAt(dataGrid.SelectedIndex);
                }
                else
                {
                    //change color to red
                }
                break;

            case ClientType.Vuze:
                if (await Task.Run(() => vuze.SendMagnetURI(clientSettings, magnet)))
                {
                    dataGrid.Items.RemoveAt(dataGrid.SelectedIndex);
                }
                else
                {
                    //change color to red
                }
                break;
            }
        }
        void AddRequests(IPeerWithMessaging peer, IReadOnlyList <IPeerWithMessaging> allPeers, int startPieceIndex, int endPieceIndex, int maxDuplicates, int?preferredMaxRequests = null)
        {
            if (!peer.CanRequestMorePieces)
            {
                return;
            }

            int preferredRequestAmount = peer.PreferredRequestAmount(TorrentData.PieceLength);
            var maxRequests            = Math.Min(preferredMaxRequests ?? 3, peer.MaxPendingRequests);

            if (peer.AmRequestingPiecesCount >= maxRequests)
            {
                return;
            }

            // FIXME: Add a test to ensure we do not unintentionally request blocks off peers which are choking us.
            // This used to say if (!peer.IsChoing || peer.SupportsFastPeer), and with the recent changes we might
            // not actually guarantee that 'ContinueExistingRequest' or 'ContinueAnyExistingRequest' properly takes
            // into account that a peer which is choking us can *only* resume a 'fast piece' in the 'AmAllowedfastPiece' list.
            if (!peer.IsChoking)
            {
                while (peer.AmRequestingPiecesCount < maxRequests)
                {
                    BlockInfo?request = Picker.ContinueAnyExistingRequest(peer, startPieceIndex, endPieceIndex, maxDuplicates);
                    if (request != null)
                    {
                        peer.EnqueueRequest(request.Value);
                    }
                    else
                    {
                        break;
                    }
                }
            }

            // If the peer supports fast peer and they are choking us, they'll still send pieces in the allowed fast set.
            if (peer.SupportsFastPeer && peer.IsChoking)
            {
                while (peer.AmRequestingPiecesCount < maxRequests)
                {
                    BlockInfo?request = Picker.ContinueExistingRequest(peer, startPieceIndex, endPieceIndex);
                    if (request != null)
                    {
                        peer.EnqueueRequest(request.Value);
                    }
                    else
                    {
                        break;
                    }
                }
            }

            // Should/could we simplify things for IPiecePicker implementations by guaranteeing IPiecePicker.PickPiece calls will
            // only be made to pieces which *can* be requested? Why not!
            // FIXME add a test for this.
            if (!peer.IsChoking || (peer.SupportsFastPeer && peer.IsAllowedFastPieces.Count > 0))
            {
                MutableBitField filtered = null;
                while (peer.AmRequestingPiecesCount < maxRequests)
                {
                    filtered ??= GenerateAlreadyHaves().Not().And(peer.BitField);
                    IList <BlockInfo> request = PriorityPick(peer, filtered, allPeers, preferredRequestAmount, 0, TorrentData.PieceCount() - 1);
                    if (request != null && request.Count > 0)
                    {
                        peer.EnqueueRequests(request);
                    }
                    else
                    {
                        break;
                    }
                }
            }

            if (!peer.IsChoking && peer.AmRequestingPiecesCount == 0)
            {
                while (peer.AmRequestingPiecesCount < maxRequests)
                {
                    BlockInfo?request = Picker.ContinueAnyExistingRequest(peer, HighPriorityPieceIndex, TorrentData.PieceCount() - 1, 1);
                    if (request != null)
                    {
                        peer.EnqueueRequest(request.Value);
                    }
                    else
                    {
                        break;
                    }
                }
            }
        }
        public void AddRequests(IReadOnlyList <IPeerWithMessaging> peers)
        {
            if (!RefreshAfterSeeking || TorrentData is null)
            {
                return;
            }

            RefreshAfterSeeking = false;
            var allPeers = peers
                           .OrderBy(t => - t.DownloadSpeed)
                           .ToArray();

            // It's only worth cancelling requests for peers which support cancellation. This is part of
            // of the fast peer extensions. For peers which do not support cancellation all we can do is
            // close the connection or allow the existing request queue to drain naturally.
            var start = HighPriorityPieceIndex;
            var end   = Math.Min(TorrentData.PieceCount() - 1, start + HighPriorityCount - 1);

            var bitfield = GenerateAlreadyHaves();

            if (bitfield.FirstFalse(start, end) != -1)
            {
                foreach (var peer in allPeers.Where(p => p.CanCancelRequests))
                {
                    if (HighPriorityPieceIndex > 0)
                    {
                        peer.EnqueueCancellations(HighPriorityPicker !.CancelRequests(peer, 0, HighPriorityPieceIndex - 1));
                    }

                    if (HighPriorityPieceIndex + HighPriorityCount < bitfield.Length)
                    {
                        peer.EnqueueCancellations(HighPriorityPicker !.CancelRequests(peer, HighPriorityPieceIndex + HighPriorityCount, bitfield.Length - 1));
                    }
                }
            }

            var fastestPeers = allPeers
                               .Where(t => t.DownloadSpeed > 50 * 1024)
                               .ToArray();

            // Queue up 12 pieces for each of our fastest peers. At a download
            // speed of 50kB/sec this should be 3 seconds of transfer for each peer.
            // We queue from peers which support cancellation first as their queue
            // is likely to be empty.
            foreach (var supportsFastPeer in new[] { true, false })
            {
                for (int i = 0; i < 4; i++)
                {
                    foreach (var peer in fastestPeers.Where(p => p.SupportsFastPeer == supportsFastPeer))
                    {
                        AddRequests(peer, peers, HighPriorityPieceIndex, Math.Min(HighPriorityPieceIndex + 1, bitfield.Length - 1), 2, preferredMaxRequests: (i + 1) * 2);
                    }
                }
            }

            // Then fill up the request queues for all peers
            foreach (var peer in peers)
            {
                AddRequests(peer, peers);
            }
        }