-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathTorrentClient.cs
304 lines (258 loc) · 9.78 KB
/
TorrentClient.cs
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
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.IO;
using System.Linq;
using System.Net;
using System.Text;
using System.Threading;
using MonoTorrent.BEncoding;
using MonoTorrent.Client;
using MonoTorrent.Client.Encryption;
using MonoTorrent.Common;
namespace BitTorrent_client
{
public class TorrentClient
{
private ClientEngine _engine;
public int TotalUploadSpeed
{
get { return _engine.TotalUploadSpeed; }
}
public int TotalDownloadSpeed
{
get { return _engine.TotalDownloadSpeed; }
}
public int DiskReadRate
{
get { return _engine.DiskManager.ReadRate; }
}
public int DiskWriteRate
{
get { return _engine.DiskManager.WriteRate; }
}
public long TotalRead
{
get { return _engine.DiskManager.TotalRead; }
}
public long TotalWritten
{
get { return _engine.DiskManager.TotalWritten; }
}
public int OpenConnections
{
get { return _engine.ConnectionManager.OpenConnections; }
}
public int Port { get; set; }
public string DownloadPath { get; set; }
public string TorrentPath { get; set; }
public string FastResumeFile { get; set; }
private IList<TorrentManager> _torrents;
private ObservableCollection<TorrentData> _torrentData;
public TorrentClient(ObservableCollection<TorrentData> torrentDatas)
{
_torrentData = torrentDatas;
_torrents = new List<TorrentManager>();
Port = 8080;
DownloadPath = Path.Combine(Environment.CurrentDirectory, "Downloads");
TorrentPath = Path.Combine(Environment.CurrentDirectory, "Torrents");
FastResumeFile = Path.Combine(TorrentPath, "fastresume.data");
if (!Directory.Exists(DownloadPath))
Directory.CreateDirectory(DownloadPath);
if (!Directory.Exists(TorrentPath))
Directory.CreateDirectory(TorrentPath);
StartEngine();
}
/// <summary>
/// Start listening on specific port
/// </summary>
private void StartEngine()
{
var engineSettings = new EngineSettings(DownloadPath, Port);
engineSettings.PreferEncryption = false;
engineSettings.AllowedEncryption = EncryptionTypes.All;
_engine = new ClientEngine(engineSettings);
_engine.ChangeListenEndpoint(new IPEndPoint(IPAddress.Any, Port));
foreach (string file in from t in Directory.GetFiles(TorrentPath)
where t.EndsWith(".torrent")
select t)
{
AddTorrent(file);
}
}
/// <summary>
/// Gets default settings for torrent
/// </summary>
/// <returns></returns>
private TorrentSettings GetDefaultTorrentSettings()
{
// 4 Upload slots - a good ratio is one slot per 5kB of upload speed
// 50 open connections - should never really need to be changed
// Unlimited download speed - valid range from 0 -> int.Max
// Unlimited upload speed - valid range from 0 -> int.Max
var torrentDefaults = new TorrentSettings(4, 150, 0, 0);
return torrentDefaults;
}
/// <summary>
/// Gets a fast resume file
/// </summary>
/// <returns></returns>
private BEncodedDictionary GetFastResume()
{
try
{
return BEncodedValue.Decode<BEncodedDictionary>(File.ReadAllBytes(FastResumeFile));
}
catch
{
return new BEncodedDictionary();
}
}
/// <summary>
/// Adds a torrent file to a client
/// </summary>
/// <param name="file">Path to torrent</param>
public void AddTorrent(string file)
{
var fileInfo = new FileInfo(file);
var newFile = Path.Combine(TorrentPath, fileInfo.Name);
if (!File.Exists(newFile))
File.Copy(file, newFile);
Torrent torrent = Torrent.Load(newFile);
if (_engine.Contains(torrent.InfoHash))
return;
TorrentManager manager = new TorrentManager(torrent, DownloadPath, GetDefaultTorrentSettings());
var fastResume = GetFastResume();
if (fastResume.ContainsKey(torrent.InfoHash.ToHex()))
manager.LoadFastResume(
new FastResume((BEncodedDictionary)fastResume[torrent.InfoHash.ToHex()]));
_engine.Register(manager);
_torrents.Add(manager);
_torrentData.Add(GetTorrentData(manager));
manager.Start();
}
/// <summary>
/// Finds a TorrentManager with specific TorrentHash
/// </summary>
/// <param name="hash"></param>
/// <returns></returns>
private TorrentManager FindTorrentByHash(TorrentHash hash)
{
return (from t in _torrents
where t.InfoHash.ToHex() == hash.ToString()
select t).SingleOrDefault();
}
/// <summary>
/// Removes a torrent from a client with specific hash
/// </summary>
/// <param name="hash"></param>
public void RemoveTorrent(TorrentHash hash)
{
var torrentManager = FindTorrentByHash(hash);
if (torrentManager != null)
{
TorrentData data = (from d in _torrentData
where d.Hash.ToString() == torrentManager.InfoHash.ToHex()
select d).SingleOrDefault();
_torrentData.Remove(data);
torrentManager.Stop();
_engine.Unregister(torrentManager);
_torrents.Remove(torrentManager);
if (File.Exists(torrentManager.Torrent.TorrentPath))
File.Delete(torrentManager.Torrent.TorrentPath);
}
}
/// <summary>
/// Pauses a torrent with specific hash
/// </summary>
/// <param name="hash"></param>
public void PauseTorrent(TorrentHash hash)
{
var torrentManager = FindTorrentByHash(hash);
if (torrentManager != null)
torrentManager.Pause();
}
/// <summary>
/// Stops a torrent with specific hash
/// </summary>
/// <param name="hash"></param>
public void StopTorrent(TorrentHash hash)
{
var torrentManager = FindTorrentByHash(hash);
if (torrentManager != null)
torrentManager.Stop();
}
/// <summary>
/// Starts a torrent with specific hash
/// </summary>
/// <param name="hash"></param>
public void StartTorrent(TorrentHash hash)
{
var torrentManager = FindTorrentByHash(hash);
if (torrentManager != null)
torrentManager.Start();
}
/// <summary>
/// Returns a collection of TorrentData
/// </summary>
/// <returns></returns>
public TorrentData GetTorrentData(TorrentManager torrent)
{
return new TorrentData()
{
DownloadSpeed = torrent.Monitor.DownloadSpeed,
Hash = new TorrentHash(torrent.InfoHash.ToHex()),
Peers = torrent.Peers.Leechs,
Progress = torrent.Progress,
Seeds = torrent.Peers.Seeds,
Size = torrent.Torrent.Size,
Status = (TorrentStatus) torrent.State,
TorrentName = torrent.Torrent.Name,
UploadSpeed = torrent.Monitor.UploadSpeed
};
}
/// <summary>
/// Updates ObservableCollection added in constructor with new data.
/// </summary>
public void UpdateTorrentData()
{
foreach (var torrent in _torrents)
{
foreach (var data in (from data in _torrentData
where torrent.InfoHash.ToHex() == data.Hash.ToString()
select data))
{
data.DownloadSpeed = torrent.Monitor.DownloadSpeed;
data.Hash = new TorrentHash(torrent.InfoHash.ToHex());
data.Peers = torrent.Peers.Leechs;
data.Progress = torrent.Progress;
data.Seeds = torrent.Peers.Seeds;
data.Size = torrent.Torrent.Size;
data.Status = (TorrentStatus)torrent.State;
data.TorrentName = torrent.Torrent.Name;
data.UploadSpeed = torrent.Monitor.UploadSpeed;
}
}
}
/// <summary>
/// Shutdowns torrent client and saves unfinished torrents to resume file
/// This method must be called when Exit button is pressed!
/// </summary>
public void Shutdown()
{
var fastResume = new BEncodedDictionary();
foreach (var torrent in _torrents)
{
torrent.Stop();
while (torrent.State != TorrentState.Stopped)
{
Thread.Sleep(250);
}
fastResume.Add(torrent.Torrent.InfoHash.ToHex(), torrent.SaveFastResume().Encode());
}
File.WriteAllBytes(FastResumeFile, fastResume.Encode());
_engine.Dispose();
Thread.Sleep(2000);
}
}
}