PageRenderTime 49ms CodeModel.GetById 23ms RepoModel.GetById 0ms app.codeStats 0ms

/Code/monotorrent-base/src/SampleClient/main.cs

https://bitbucket.org/foens/p2pp
C# | 301 lines | 228 code | 36 blank | 37 comment | 25 complexity | 4ecb65116b3891cd6be22f839c1c2443 MD5 | raw file
  1. using System;
  2. using System.Collections.Generic;
  3. using System.Text;
  4. using System.Net.Sockets;
  5. using System.IO;
  6. using MonoTorrent.Common;
  7. using MonoTorrent.Client;
  8. using System.Net;
  9. using System.Diagnostics;
  10. using System.Threading;
  11. using MonoTorrent.BEncoding;
  12. using MonoTorrent.Client.Encryption;
  13. using MonoTorrent.Client.Tracker;
  14. using MonoTorrent.Dht;
  15. using MonoTorrent.Dht.Listeners;
  16. namespace MonoTorrent
  17. {
  18. class main
  19. {
  20. static string dhtNodeFile;
  21. static string basePath;
  22. static string downloadsPath;
  23. static string fastResumeFile;
  24. static string torrentsPath;
  25. static ClientEngine engine; // The engine used for downloading
  26. static List<TorrentManager> torrents; // The list where all the torrentManagers will be stored that the engine gives us
  27. static Top10Listener listener; // This is a subclass of TraceListener which remembers the last 20 statements sent to it
  28. static int uploadLimit;
  29. static void Main(string[] args)
  30. {
  31. if (Convert.ToBoolean(args[1]))
  32. uploadLimit = Convert.ToInt32(args[2]);
  33. /* Generate the paths to the folder we will save .torrent files to and where we download files to */
  34. basePath = args[0]; //Environment.CurrentDirectory; // This is the directory we are currently in
  35. torrentsPath = Path.Combine(basePath, "Torrents"); // This is the directory we will save .torrents to
  36. downloadsPath = Path.Combine(basePath, "Downloads"); // This is the directory we will save downloads to
  37. fastResumeFile = Path.Combine(torrentsPath, "fastresume.data");
  38. dhtNodeFile = Path.Combine(basePath, "DhtNodes");
  39. torrents = new List<TorrentManager>(); // This is where we will store the torrentmanagers
  40. listener = new Top10Listener(10);
  41. // We need to cleanup correctly when the user closes the window by using ctrl-c
  42. // or an unhandled exception happens
  43. Console.CancelKeyPress += delegate { shutdown(); };
  44. AppDomain.CurrentDomain.ProcessExit += delegate { shutdown(); };
  45. AppDomain.CurrentDomain.UnhandledException += delegate(object sender, UnhandledExceptionEventArgs e) { Console.WriteLine(e.ExceptionObject); shutdown(); };
  46. Thread.GetDomain().UnhandledException += delegate(object sender, UnhandledExceptionEventArgs e) { Console.WriteLine(e.ExceptionObject); shutdown(); };
  47. StartEngine(Convert.ToBoolean(args[1]));
  48. }
  49. private static void StartEngine(bool limitUpload)
  50. {
  51. int port;
  52. Torrent torrent = null;
  53. // Ask the user what port they want to use for incoming connections
  54. Console.Write(Environment.NewLine + "Choose a listen port: ");
  55. while (!Int32.TryParse(Console.ReadLine(), out port)) { }
  56. // Create the settings which the engine will use
  57. // downloadsPath - this is the path where we will save all the files to
  58. // port - this is the port we listen for connections on
  59. EngineSettings engineSettings = new EngineSettings(downloadsPath, port);
  60. engineSettings.PreferEncryption = false;
  61. engineSettings.AllowedEncryption = EncryptionTypes.All;
  62. if (limitUpload)
  63. engineSettings.GlobalMaxUploadSpeed = uploadLimit;
  64. //engineSettings.GlobalMaxDownloadSpeed = 100 * 1024;
  65. //engineSettings.MaxReadRate = 1 * 1024 * 1024;
  66. // Create the default settings which a torrent will have.
  67. // 4 Upload slots - a good ratio is one slot per 5kB of upload speed
  68. // 50 open connections - should never really need to be changed
  69. // Unlimited download speed - valid range from 0 -> int.Max
  70. // Unlimited upload speed - valid range from 0 -> int.Max
  71. TorrentSettings torrentDefaults = new TorrentSettings(4, 150, 0, 0);
  72. // Create an instance of the engine.
  73. engine = new ClientEngine(engineSettings);
  74. engine.ChangeListenEndpoint(new IPEndPoint(IPAddress.Any, port));
  75. byte[] nodes = null;
  76. try
  77. {
  78. nodes = File.ReadAllBytes(dhtNodeFile);
  79. }
  80. catch
  81. {
  82. Console.WriteLine("No existing dht nodes could be loaded");
  83. }
  84. DhtListener dhtListner = new DhtListener (new IPEndPoint (IPAddress.Any, port));
  85. DhtEngine dht = new DhtEngine (dhtListner);
  86. //engine.RegisterDht(dht);
  87. // dhtListner.Start();
  88. // engine.DhtEngine.Start(nodes);
  89. // If the SavePath does not exist, we want to create it.
  90. if (!Directory.Exists(engine.Settings.SavePath))
  91. Directory.CreateDirectory(engine.Settings.SavePath);
  92. // If the torrentsPath does not exist, we want to create it
  93. if (!Directory.Exists(torrentsPath))
  94. Directory.CreateDirectory(torrentsPath);
  95. BEncodedDictionary fastResume;
  96. try
  97. {
  98. fastResume = BEncodedValue.Decode<BEncodedDictionary>(File.ReadAllBytes(fastResumeFile));
  99. }
  100. catch
  101. {
  102. fastResume = new BEncodedDictionary();
  103. }
  104. // For each file in the torrents path that is a .torrent file, load it into the engine.
  105. foreach (string file in Directory.GetFiles(torrentsPath))
  106. {
  107. if (file.EndsWith(".torrent"))
  108. {
  109. try
  110. {
  111. // Load the .torrent from the file into a Torrent instance
  112. // You can use this to do preprocessing should you need to
  113. torrent = Torrent.Load(file);
  114. Console.WriteLine(torrent.InfoHash.ToString());
  115. }
  116. catch (Exception e)
  117. {
  118. Console.Write("Couldn't decode {0}: ", file);
  119. Console.WriteLine(e.Message);
  120. continue;
  121. }
  122. // When any preprocessing has been completed, you create a TorrentManager
  123. // which you then register with the engine.
  124. TorrentManager manager = new TorrentManager(torrent, downloadsPath, torrentDefaults);
  125. if (fastResume.ContainsKey(torrent.InfoHash.ToHex ()))
  126. manager.LoadFastResume(new FastResume ((BEncodedDictionary)fastResume[torrent.infoHash.ToHex ()]));
  127. engine.Register(manager);
  128. // Store the torrent manager in our list so we can access it later
  129. torrents.Add(manager);
  130. manager.PeersFound += new EventHandler<PeersAddedEventArgs>(manager_PeersFound);
  131. }
  132. }
  133. // If we loaded no torrents, just exist. The user can put files in the torrents directory and start
  134. // the client again
  135. if (torrents.Count == 0)
  136. {
  137. Console.WriteLine("No torrents found in the Torrents directory");
  138. Console.WriteLine("Exiting...");
  139. engine.Dispose();
  140. return;
  141. }
  142. // For each torrent manager we loaded and stored in our list, hook into the events
  143. // in the torrent manager and start the engine.
  144. foreach (TorrentManager manager in torrents)
  145. {
  146. // Every time a piece is hashed, this is fired.
  147. manager.PieceHashed += delegate(object o, PieceHashedEventArgs e) {
  148. lock (listener)
  149. listener.WriteLine(string.Format("Piece Hashed: {0} - {1}", e.PieceIndex, e.HashPassed ? "Pass" : "Fail"));
  150. };
  151. // Every time the state changes (Stopped -> Seeding -> Downloading -> Hashing) this is fired
  152. manager.TorrentStateChanged += delegate (object o, TorrentStateChangedEventArgs e) {
  153. lock (listener)
  154. listener.WriteLine("OldState: " + e.OldState.ToString() + " NewState: " + e.NewState.ToString());
  155. };
  156. // Every time the tracker's state changes, this is fired
  157. foreach (TrackerTier tier in manager.TrackerManager)
  158. {
  159. foreach (MonoTorrent.Client.Tracker.Tracker t in tier.Trackers)
  160. {
  161. t.AnnounceComplete += delegate(object sender, AnnounceResponseEventArgs e) {
  162. listener.WriteLine(string.Format("{0}: {1}", e.Successful, e.Tracker.ToString()));
  163. };
  164. }
  165. }
  166. // Start the torrentmanager. The file will then hash (if required) and begin downloading/seeding
  167. manager.Start();
  168. }
  169. // While the torrents are still running, print out some stats to the screen.
  170. // Details for all the loaded torrent managers are shown.
  171. int i = 0;
  172. bool running = true;
  173. StringBuilder sb = new StringBuilder(1024);
  174. while (running)
  175. {
  176. if ((i++) % 10 == 0)
  177. {
  178. sb.Remove(0, sb.Length);
  179. running = torrents.Exists(delegate(TorrentManager m) { return m.State != TorrentState.Stopped; });
  180. AppendFormat(sb, "Total Download Rate: {0:0.00}kB/sec", engine.TotalDownloadSpeed / 1024.0);
  181. AppendFormat(sb, "Total Upload Rate: {0:0.00}kB/sec", engine.TotalUploadSpeed / 1024.0);
  182. AppendFormat(sb, "Disk Read Rate: {0:0.00} kB/s", engine.DiskManager.ReadRate / 1024.0);
  183. AppendFormat(sb, "Disk Write Rate: {0:0.00} kB/s", engine.DiskManager.WriteRate / 1024.0);
  184. AppendFormat(sb, "Total Read: {0:0.00} kB", engine.DiskManager.TotalRead / 1024.0);
  185. AppendFormat(sb, "Total Written: {0:0.00} kB", engine.DiskManager.TotalWritten / 1024.0);
  186. AppendFormat(sb, "Open Connections: {0}", engine.ConnectionManager.OpenConnections);
  187. foreach (TorrentManager manager in torrents)
  188. {
  189. AppendSeperator(sb);
  190. AppendFormat(sb, "State: {0}", manager.State);
  191. AppendFormat(sb, "Name: {0}", manager.Torrent == null ? "MetaDataMode" : manager.Torrent.Name);
  192. AppendFormat(sb, "Progress: {0:0.00}", manager.Progress);
  193. AppendFormat(sb, "Download Speed: {0:0.00} kB/s", manager.Monitor.DownloadSpeed / 1024.0);
  194. AppendFormat(sb, "Upload Speed: {0:0.00} kB/s", manager.Monitor.UploadSpeed / 1024.0);
  195. AppendFormat(sb, "Total Downloaded: {0:0.00} MB", manager.Monitor.DataBytesDownloaded / (1024.0 * 1024.0));
  196. AppendFormat(sb, "Total Uploaded: {0:0.00} MB", manager.Monitor.DataBytesUploaded / (1024.0 * 1024.0));
  197. MonoTorrent.Client.Tracker.Tracker tracker = manager.TrackerManager.CurrentTracker;
  198. //AppendFormat(sb, "Tracker Status: {0}", tracker == null ? "<no tracker>" : tracker.State.ToString());
  199. AppendFormat(sb, "Warning Message: {0}", tracker == null ? "<no tracker>" : tracker.WarningMessage);
  200. AppendFormat(sb, "Failure Message: {0}", tracker == null ? "<no tracker>" : tracker.FailureMessage);
  201. if (manager.PieceManager != null)
  202. AppendFormat(sb, "Current Requests: {0}", manager.PieceManager.CurrentRequestCount());
  203. foreach (PeerId p in manager.GetPeers())
  204. AppendFormat(sb, "\t{2} - {1:0.00}/{3:0.00}kB/sec - {0}", p.Peer.ConnectionUri,
  205. p.Monitor.DownloadSpeed / 1024.0,
  206. p.AmRequestingPiecesCount,
  207. p.Monitor.UploadSpeed/ 1024.0);
  208. AppendFormat(sb, "", null);
  209. if (manager.Torrent != null)
  210. foreach (TorrentFile file in manager.Torrent.Files)
  211. AppendFormat(sb, "{1:0.00}% - {0}", file.Path, file.BitField.PercentComplete);
  212. }
  213. Console.Clear();
  214. Console.WriteLine(sb.ToString());
  215. listener.ExportTo(Console.Out);
  216. }
  217. System.Threading.Thread.Sleep(500);
  218. }
  219. }
  220. static void manager_PeersFound(object sender, PeersAddedEventArgs e)
  221. {
  222. lock (listener)
  223. listener.WriteLine(string.Format("Found {0} new peers and {1} existing peers", e.NewPeers, e.ExistingPeers ));//throw new Exception("The method or operation is not implemented.");
  224. }
  225. private static void AppendSeperator(StringBuilder sb)
  226. {
  227. AppendFormat(sb, "", null);
  228. AppendFormat(sb, "- - - - - - - - - - - - - - - - - - - - - - - - - - - - - -", null);
  229. AppendFormat(sb, "", null);
  230. }
  231. private static void AppendFormat(StringBuilder sb, string str, params object[] formatting)
  232. {
  233. if (formatting != null)
  234. sb.AppendFormat(str, formatting);
  235. else
  236. sb.Append(str);
  237. sb.AppendLine();
  238. }
  239. private static void shutdown()
  240. {
  241. BEncodedDictionary fastResume = new BEncodedDictionary();
  242. for (int i = 0; i < torrents.Count; i++)
  243. {
  244. torrents[i].Stop(); ;
  245. while (torrents[i].State != TorrentState.Stopped)
  246. {
  247. Console.WriteLine("{0} is {1}", torrents[i].Torrent.Name, torrents[i].State);
  248. Thread.Sleep(250);
  249. }
  250. fastResume.Add(torrents[i].Torrent.InfoHash.ToHex (), torrents[i].SaveFastResume().Encode());
  251. }
  252. #if !DISABLE_DHT
  253. File.WriteAllBytes(dhtNodeFile, engine.DhtEngine.SaveNodes());
  254. #endif
  255. File.WriteAllBytes(fastResumeFile, fastResume.Encode());
  256. engine.Dispose();
  257. foreach (TraceListener lst in Debug.Listeners)
  258. {
  259. lst.Flush();
  260. lst.Close();
  261. }
  262. System.Threading.Thread.Sleep(2000);
  263. }
  264. }
  265. }