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); }
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); }
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); }
#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>(); }
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); }
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); }
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); } }
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); }
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); }
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); }
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); }
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)); }
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; } } } }
/// <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); } }