Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion Netorrent.Tests.Integration/Torrents/TorrentTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -454,7 +454,7 @@ CancellationToken cancellationToken
var seederTorrent = await seeder.CreateTorrentAsync(
path,
_fixture.AnnounceUrl,
[.. _fixture.AnnounceUrls]
[_fixture.AnnounceUrls]
);

yield return (seederTorrent, seeder);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -207,16 +207,16 @@ namespace Netorrent.TorrentFile.FileStructure
}
public class MetaInfo : System.IEquatable<Netorrent.TorrentFile.FileStructure.MetaInfo>
{
public MetaInfo(Netorrent.TorrentFile.FileStructure.Info Info, string Announce, System.Collections.Generic.List<string>? AnnounceList = null, long? CreationDate = default, string? Comment = null, string? CreatedBy = null, string? Encoding = null, string? Title = null, System.Collections.Generic.List<string>? UrlList = null) { }
public MetaInfo(Netorrent.TorrentFile.FileStructure.Info Info, string Announce, System.Collections.Generic.IReadOnlyList<string[]>? AnnounceList = null, long? CreationDate = default, string? Comment = null, string? CreatedBy = null, string? Encoding = null, string? Title = null, System.Collections.Generic.IReadOnlyList<string>? UrlList = null) { }
public string Announce { get; init; }
public System.Collections.Generic.List<string>? AnnounceList { get; init; }
public System.Collections.Generic.IReadOnlyList<string[]>? AnnounceList { get; init; }
public string? Comment { get; init; }
public string? CreatedBy { get; init; }
public long? CreationDate { get; init; }
public string? Encoding { get; init; }
public Netorrent.TorrentFile.FileStructure.Info Info { get; init; }
public string? Title { get; init; }
public System.Collections.Generic.List<string>? UrlList { get; init; }
public System.Collections.Generic.IReadOnlyList<string>? UrlList { get; init; }
public Netorrent.Bencoding.Structs.BDictionary ToBDictionary() { }
}
}
Expand Down Expand Up @@ -265,7 +265,7 @@ namespace Netorrent.TorrentFile
public sealed class TorrentClient : System.IAsyncDisposable
{
public TorrentClient(System.Func<Netorrent.TorrentFile.Options.TorrentClientOptions, Netorrent.TorrentFile.Options.TorrentClientOptions>? action = null) { }
public System.Threading.Tasks.ValueTask<Netorrent.TorrentFile.Torrent> CreateTorrentAsync(string path, string announceUrl, System.Collections.Generic.List<string>? announceUrls = null, System.Collections.Generic.List<string>? webUrls = null, int pieceLength = 262144, System.Threading.CancellationToken cancellationToken = default) { }
public System.Threading.Tasks.ValueTask<Netorrent.TorrentFile.Torrent> CreateTorrentAsync(string path, string announceUrl, System.Collections.Generic.List<string[]>? announceUrls = null, System.Collections.Generic.List<string>? webUrls = null, int pieceLength = 262144, System.Threading.CancellationToken cancellationToken = default) { }
public System.Threading.Tasks.ValueTask DisposeAsync() { }
public Netorrent.TorrentFile.Torrent LoadTorrent(Netorrent.TorrentFile.FileStructure.MetaInfo metaInfo, string outputDirectory, int[]? downloadedPieces = null) { }
public System.Threading.Tasks.ValueTask<Netorrent.TorrentFile.Torrent> LoadTorrentAsync(string path, string outputDirectory, int[]? downloadedPieces = null, System.Threading.CancellationToken cancellationToken = default) { }
Expand Down
24 changes: 18 additions & 6 deletions Netorrent.Tests/Torrents/TorrentFileTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -64,7 +64,9 @@ public async Task Should_Create_Torrent_File_From_Directory(CancellationToken ca
await using var torrent = await torrentClient.CreateTorrentAsync(
"Data/MultifileTest",
"http://test.com",
["http://test.com"],
[
["http://test.com"],
],
["http://test.com"],
cancellationToken: cancellationToken
);
Expand All @@ -90,7 +92,9 @@ public async Task Should_Create_Torrent_File_From_File(CancellationToken cancell
await using var torrent = await torrentClient.CreateTorrentAsync(
"Data/MultifileTest/test.txt",
"http://test.com",
["http://test.com"],
[
["http://test.com"],
],
["http://test.com"],
cancellationToken: cancellationToken
);
Expand All @@ -112,7 +116,9 @@ await torrentClient
.CreateTorrentAsync(
"Data/ASdasd",
"http://test.com",
["http://test.com"],
[
["http://test.com"],
],
["http://test.com"],
cancellationToken: cancellationToken
)
Expand All @@ -128,7 +134,9 @@ await torrentClient
.CreateTorrentAsync(
"Data/MultifileTest/adasdasd.txt",
"http://test.com",
["http://test.com"],
[
["http://test.com"],
],
["http://test.com"],
cancellationToken: cancellationToken
)
Expand All @@ -146,7 +154,9 @@ public async Task Should_Verify_File(string path, CancellationToken cancellation
await using var torrent = await torrentClient.CreateTorrentAsync(
path,
"http://test.com",
["http://test.com"],
[
["http://test.com"],
],
["http://test.com"],
pieceLength: pieceLength,
cancellationToken: cancellationToken
Expand Down Expand Up @@ -177,7 +187,9 @@ CancellationToken cancellationToken
await using var torrent = await torrentClient.CreateTorrentAsync(
path,
"http://test.com",
["http://test.com"],
[
["http://test.com"],
],
["http://test.com"],
pieceLength: pieceLength,
cancellationToken: cancellationToken
Expand Down
127 changes: 84 additions & 43 deletions Netorrent.Tests/Tracker/TrackerTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
using System.Threading.Channels;
using Microsoft.Extensions.Logging;
using Microsoft.Extensions.Logging.Abstractions;
using Netorrent.Exceptions;
using Netorrent.Extensions;
using Netorrent.Tests.Extensions;
using Netorrent.Tests.Fakes;
Expand Down Expand Up @@ -69,9 +70,7 @@ public async Task Should_get_peers_from_udp_tracker(CancellationToken cancellati
new(),
ctx.Channel.Writer,
new byte[20],
"null",
new(IPAddress.Loopback, 1),
ctx.Logger
new(IPAddress.Loopback, 1)
);

using var cts = CancellationTokenSource.CreateLinkedTokenSource(cancellationToken);
Expand Down Expand Up @@ -102,7 +101,6 @@ public async Task Should_get_peers_from_http_tracker(CancellationToken cancellat
new(),
new byte[20],
"null",
ctx.Logger,
ctx.Channel
);

Expand Down Expand Up @@ -134,23 +132,13 @@ public async Task Should_not_get_peers_from_http_tracker(CancellationToken cance
new(),
new byte[20],
"null",
ctx.Logger,
ctx.Channel
);

using var cts = CancellationTokenSource.CreateLinkedTokenSource(cancellationToken);
var trackerTask = httpTracker.StartAsync(cts.Token).AsTask();

await Task.Delay(5.Seconds, cancellationToken);
cts.Cancel();
ctx.Channel.Writer.TryComplete();

var ipendpoints = await ctx
.Channel.Reader.ReadAllAsync(cancellationToken)
.ToArrayAsync(cancellationToken: cancellationToken)
.AsTask();

ipendpoints.Length.ShouldBe(0);
await httpTracker
.StartAsync(cancellationToken)
.AsTask()
.ShouldThrowAsync<AnnounceException>();
}

[Test]
Expand All @@ -171,43 +159,97 @@ public async Task Should_not_get_peers_from_udp_tracker(CancellationToken cancel
new(),
ctx.Channel.Writer,
new byte[20],
"null",
new(IPAddress.Loopback, 1),
ctx.Logger
new(IPAddress.Loopback, 1)
);

using var cts = CancellationTokenSource.CreateLinkedTokenSource(cancellationToken);
var trackerTask = udptracker.StartAsync(cts.Token).AsTask();
await udptracker
.StartAsync(cancellationToken)
.AsTask()
.ShouldThrowAsync<AnnounceException>();
}

await Task.Delay(5.Seconds, cancellationToken);
cts.Cancel();
ctx.Channel.Writer.TryComplete();
[Test]
public async Task Should_not_get_peers_from_tracker_client(CancellationToken cancellationToken)
{
var ctx = CreateDefaultContext();

var ipendpoints = await ctx
.Channel.Reader.ReadAllAsync(cancellationToken)
.ToArrayAsync(cancellationToken: cancellationToken)
.AsTask();
await using var udptrackerManagerv4 = new FakeUdpTrackerTransactionManager(
[.. ctx.Ips.Where(i => i.AddressFamily == AddressFamily.InterNetwork)],
ctx.Interval,
new Exception()
);

await using var udptrackerManagerv6 = new FakeUdpTrackerTransactionManager(
[.. ctx.Ips.Where(i => i.AddressFamily == AddressFamily.InterNetworkV6)],
ctx.Interval,
new Exception()
);

ipendpoints.Length.ShouldBe(0);
using var httpTrackerHandlerv4 = new FakeHttpTrackerHandler(
[.. ctx.Ips.Where(i => i.AddressFamily == AddressFamily.InterNetwork)],
ctx.Interval,
new Exception()
);
using var httpTrackerHandlerv6 = new FakeHttpTrackerHandler(
[.. ctx.Ips.Where(i => i.AddressFamily == AddressFamily.InterNetworkV6)],
ctx.Interval,
new Exception()
);

var trackerHandlers = new TrackerHandlers(
httpTrackerHandlerv4,
udptrackerManagerv4,
httpTrackerHandlerv6,
udptrackerManagerv6
);

await using var trackerClient = new TrackerClient(
trackerHandlers,
UsedTrackers.Http | UsedTrackers.Udp,
1,
new(3),
new(),
ctx.Channel,
[
["udp://localhost:1", "https://localhost:2"],
["http://localhost:3", "aaaa://localhost:4"],
],
new byte[20],
ctx.Logger
);

await trackerClient.StartAsync(cancellationToken).ShouldNotThrowAsync();
}

[Test]
public async Task Should_get_peers_from_tracker_client(CancellationToken cancellationToken)
{
var ctx = CreateDefaultContext();

await using var udptrackerManager = new FakeUdpTrackerTransactionManager(
ctx.Ips,
await using var udptrackerManagerv4 = new FakeUdpTrackerTransactionManager(
[.. ctx.Ips.Where(i => i.AddressFamily == AddressFamily.InterNetwork)],
ctx.Interval
);

await using var udptrackerManagerv6 = new FakeUdpTrackerTransactionManager(
[.. ctx.Ips.Where(i => i.AddressFamily == AddressFamily.InterNetworkV6)],
ctx.Interval
);

var httpTrackerHandler = new FakeHttpTrackerHandler(ctx.Ips, ctx.Interval);
using var httpTrackerHandlerv4 = new FakeHttpTrackerHandler(
[.. ctx.Ips.Where(i => i.AddressFamily == AddressFamily.InterNetwork)],
ctx.Interval
);
using var httpTrackerHandlerv6 = new FakeHttpTrackerHandler(
[.. ctx.Ips.Where(i => i.AddressFamily == AddressFamily.InterNetworkV6)],
ctx.Interval
);

var trackerHandlers = new TrackerHandlers(
httpTrackerHandler,
udptrackerManager,
httpTrackerHandler,
udptrackerManager
httpTrackerHandlerv4,
udptrackerManagerv4,
httpTrackerHandlerv6,
udptrackerManagerv6
);

await using var trackerClient = new TrackerClient(
Expand All @@ -218,10 +260,8 @@ public async Task Should_get_peers_from_tracker_client(CancellationToken cancell
new(),
ctx.Channel,
[
"udp://localhost:1",
"https://localhost:2",
"http://localhost:3",
"aaaa://localhost:4",
["udp://localhost:1", "https://localhost:2"],
["http://localhost:3", "aaaa://localhost:4"],
],
new byte[20],
ctx.Logger
Expand All @@ -239,6 +279,7 @@ public async Task Should_get_peers_from_tracker_client(CancellationToken cancell

IPEndPoint[] resultIps = [.. ctx.Ips, .. ctx.Ips, .. ctx.Ips, .. ctx.Ips];
ipendpoints.Length.ShouldBe(ctx.Ips.Length * 4);
ipendpoints.ShouldBe(resultIps);
var sorted = ipendpoints.OrderBy(i => i.ToString()).ToArray();
sorted.ShouldBe([.. resultIps.OrderBy(i => i.ToString())]);
}
}
3 changes: 3 additions & 0 deletions Netorrent/Exceptions/AnnounceException.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
namespace Netorrent.Exceptions;

internal class AnnounceException(string? message = null) : Exception(message);
2 changes: 1 addition & 1 deletion Netorrent/P2P/Tcp/TcpPeersListener.cs
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ ILogger logger
{
private readonly ConcurrentDictionary<InfoHash, PeersClient> _peersClientByInfoHash = new();
private readonly Channel<TcpClient> _incomingConnections = Channel.CreateBounded<TcpClient>(
128
new BoundedChannelOptions(128) { SingleWriter = false, SingleReader = true }
);

public int Port => ((IPEndPoint)tcpListeners[0].LocalEndpoint).Port;
Expand Down
16 changes: 8 additions & 8 deletions Netorrent/TorrentFile/FileStructure/MetaInfo.cs
Original file line number Diff line number Diff line change
Expand Up @@ -5,13 +5,13 @@ namespace Netorrent.TorrentFile.FileStructure;
public record MetaInfo(
Info Info,
string Announce,
List<string>? AnnounceList = null,
IReadOnlyList<string[]>? AnnounceList = null,
long? CreationDate = null,
string? Comment = null,
string? CreatedBy = null,
string? Encoding = null,
string? Title = null,
List<string>? UrlList = null
IReadOnlyList<string>? UrlList = null
)
{
public BDictionary ToBDictionary()
Expand All @@ -23,16 +23,16 @@ public BDictionary ToBDictionary()
root.Elements["announce"] = new BString(Announce);
}

if (AnnounceList != null && AnnounceList.Count != 0)
if (AnnounceList is not null && AnnounceList.Count != 0)
{
var innerTier = new BList([
.. AnnounceList.Select(u => (IBencodingNode)new BString(u)),
root.Elements["announce-list"] = new BList([
.. AnnounceList.Select(u => new BList([
.. u.Select(i => (IBencodingNode)new BString(i)),
])),
]);
var outer = new BList([innerTier]);
root.Elements["announce-list"] = outer;
}

if (UrlList != null && UrlList.Count != 0)
if (UrlList is not null && UrlList.Count != 0)
{
root.Elements["url-list"] = new BList([
.. UrlList.Select(u => (IBencodingNode)new BString(u)),
Expand Down
6 changes: 5 additions & 1 deletion Netorrent/TorrentFile/Torrent.cs
Original file line number Diff line number Diff line change
Expand Up @@ -115,7 +115,11 @@ IReadOnlySet<int> downloadedPieces
dataStatistics,
peerId,
trackersChannel.Writer,
[metaInfo.Announce, .. metaInfo.AnnounceList ?? []],
metaInfo.AnnounceList?.Select(i => i.ToArray()).ToList() //Don't modify the original announce list
??
[
[metaInfo.Announce],
],
metaInfo.Info.InfoHash,
torrentClientOptions.Logger
);
Expand Down
Loading