Repository navigation
Expand file tree
/
Copy pathTrackerExtensions.cs
More file actions
97 lines (79 loc) · 2.99 KB
/
Copy pathTrackerExtensions.cs
File metadata and controls
97 lines (79 loc) · 2.99 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
using System.Net;
using System.Text;
using System.Web;
using codecrafters_bittorrent.Bencoding;
using codecrafters_bittorrent.Connection;
namespace codecrafters_bittorrent.Extensions;
public static class TrackerExtensions
{
public static string GetTrackerUrl(this string magnet)
{
return WebUtility.UrlDecode(magnet.Split("&tr=")[1]);
}
public static byte[] GetInfoHash(this string magnet)
{
var infoHashString = magnet.Split("&dn=")[0].Split(":")[3];
var infoHashBytes = new byte[infoHashString.Length / 2];
for (var i = 0; i < infoHashBytes.Length; i++)
{
infoHashBytes[i] = byte.Parse(infoHashString.Substring(i * 2, 2),
System.Globalization.NumberStyles.HexNumber);
}
return infoHashBytes;
}
public static async Task<List<Peer>> DiscoverPeers(string trackerUrl, byte[] infoHash, long leftLength)
{
var result = new List<Peer>();
using var httpClient = new HttpClient();
var baseUri = new Uri(trackerUrl).ToString();
var queryParameters = new Dictionary<string, string>
{
{ "info_hash", HttpUtility.UrlEncode(infoHash) },
{ "peer_id", GeneratePeerId() },
{ "port", "6881" },
{ "uploaded", "0" },
{ "downloaded", "0" },
{ "left", leftLength.ToString() },
{ "compact", "1" }
};
var queryStringBuilder = new StringBuilder();
foreach (var kvp in queryParameters)
{
if (queryStringBuilder.Length > 0)
{
queryStringBuilder.Append('&');
}
queryStringBuilder.Append($"{kvp.Key}={kvp.Value}");
}
var fullUri = $"{baseUri}?{queryStringBuilder}";
var response = await httpClient.GetAsync(fullUri);
var responseContent = await response.Content.ReadAsByteArrayAsync();
var index = 0;
var dict = BencodeDecoder.DecodeDictionary(ref responseContent, ref index);
if (dict.TryGetValue("peers"u8.ToArray(), out var peersValue))
{
var peers = (byte[])peersValue;
var peersCount = peers.Length / 6;
for (var i = 0; i < peersCount; i++)
{
var ipBytes = peers[(i * 6)..(i * 6 + 4)];
var portBytes = peers[(i * 6 + 4)..(i * 6 + 6)];
var ip = new IPAddress(ipBytes);
var port = BitConverter.ToUInt16(portBytes.Reverse().ToArray(), 0);
result.Add(new Peer(ip.ToString(), port));
}
}
else
{
Console.WriteLine("The 'peers' key was not found in the dictionary.");
}
return result;
}
public static string GeneratePeerId()
{
var random = new Random();
const string chars = "ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789";
return new string(Enumerable.Repeat(chars, 20)
.Select(s => s[random.Next(s.Length)]).ToArray());
}
}