void Start() { //Start Torrent Engine torrents = new List <TorrentManager>(); messages = new List <SimpleMessage>(); //Torrents to remove seedingLimitTorrents = new List <Tuple <DateTime, TorrentManager> >(); Console.WriteLine("simpletorrent: version {0}", VERSION); Console.WriteLine("simpletorrent: Reading configuration file (simple.cfg)..."); config = new SimpleConfiguration("simple.cfg"); string basePath = Path.GetDirectoryName(System.Reflection.Assembly.GetEntryAssembly().Location); Console.WriteLine("simpletorrent: ApplicationPath (derived) {0}", basePath); if (config.HasValue("Debug")) { debugWriter = new DebugWriter(true); Console.WriteLine("simpletorrent: Debugging Enabled!"); } else { debugWriter = new DebugWriter(false); } PlatformID os = Environment.OSVersion.Platform; if (os == PlatformID.MacOSX) { Console.WriteLine("simpletorrent: We think we're on MacOSX"); simpleOperatingSystem = SimpleTorrentOperatingMode.MacOSX; } else if (os == PlatformID.Unix) { Console.WriteLine("simpletorrent: We think we're on *nix"); simpleOperatingSystem = SimpleTorrentOperatingMode.StarNix; } else { Console.WriteLine("simpletorrent: We think we're on Windows"); simpleOperatingSystem = SimpleTorrentOperatingMode.Windows; } torrentsPath = Path.GetFullPath(config.GetValue("TorrentPath", Path.Combine(basePath, "Torrents"))); downloadsPath = Path.GetFullPath(config.GetValue("DownloadPath", Path.Combine(basePath, "Downloads"))); sslCertificatePath = Path.GetFullPath(config.GetValue("SslCertificatePath", Path.Combine(basePath, "simple.pfx"))); useECDSA = config.HasValue("SslCertificateECDSA"); fastResumeFile = Path.Combine(torrentsPath, "fastresume.data"); dhtNodeFile = Path.Combine(torrentsPath, "dht.data"); requireProtocolEncryption = config.HasValue("RequireProtocolEncryption"); sessionLimit = config.GetValueInt("SessionLimit", 20); seedingLimit = config.GetValueInt("SeedingLimit"); // If the SavePath does not exist, we want to create it. if (!Directory.Exists(downloadsPath)) { Directory.CreateDirectory(downloadsPath); } // If the torrentsPath does not exist, we want to create it if (!Directory.Exists(torrentsPath)) { Directory.CreateDirectory(torrentsPath); } downloadsPathDrive = null; string myRootPath = Path.GetPathRoot(downloadsPath).ToLower(); if (simpleOperatingSystem == SimpleTorrentOperatingMode.StarNix) { System.Diagnostics.Process proc = new System.Diagnostics.Process(); proc.EnableRaisingEvents = false; proc.StartInfo.FileName = "bash"; proc.StartInfo.Arguments = "-c \"df -h " + downloadsPath + " | awk '{print $6}' | tail -1\""; proc.StartInfo.UseShellExecute = false; proc.StartInfo.RedirectStandardOutput = true; proc.Start(); string output = proc.StandardOutput.ReadToEnd().Trim().ToLower(); proc.WaitForExit(); if (proc.ExitCode == 0) { myRootPath = output; debugWriter.WriteLine("*nix override (bash -c 'df -h <path>') - \"" + output + "\""); } } else if (simpleOperatingSystem == SimpleTorrentOperatingMode.MacOSX) { System.Diagnostics.Process proc = new System.Diagnostics.Process(); proc.EnableRaisingEvents = false; proc.StartInfo.FileName = "bash"; proc.StartInfo.Arguments = "-c \"df -h " + downloadsPath + " | awk '{print $9}' | tail -1\""; proc.StartInfo.UseShellExecute = false; proc.StartInfo.RedirectStandardOutput = true; proc.Start(); string output = proc.StandardOutput.ReadToEnd().Trim().ToLower(); proc.WaitForExit(); if (proc.ExitCode == 0) { myRootPath = output; debugWriter.WriteLine("*nix override (bash -c 'df -h <path>') - \"" + output + "\""); } } foreach (var drive in DriveInfo.GetDrives()) { debugWriter.WriteLine("Enemerating Drives - " + drive.RootDirectory.FullName.ToString()); if (drive.RootDirectory.FullName.ToLower() == myRootPath) { downloadsPathDrive = drive; break; } } Console.WriteLine("simpletorrent: TorrentPath {0}", torrentsPath); Console.WriteLine("simpletorrent: DownloadPath {0}", downloadsPath); Console.WriteLine("simpletorrent: DownloadRootPath (derived) {0}", downloadsPathDrive); Console.WriteLine("simpletorrent: SslCertificatePath {0}", sslCertificatePath); Console.WriteLine("simpletorrent: SslCertificateECDSA {0}", useECDSA ? "Yes" : "No"); Console.WriteLine("simpletorrent: RequireProtocolEncryption {0}", requireProtocolEncryption ? "Yes" : "No"); Console.WriteLine("simpletorrent: SessionLimit {0}", sessionLimit); Console.WriteLine("simpletorrent: SeedingLimit {0}", seedingLimit.HasValue ? seedingLimit.Value.ToString() : "No"); int?torrentListenPort = config.GetValueInt("TorrentListenPort"); if (!torrentListenPort.HasValue) { throw new SimpleTorrentException("Configuration does not have a proper 'TorrentListenPort' value defined", null); } Console.WriteLine("simpletorrent: TorrentListenPort {0}", torrentListenPort); externalBanList = new List <string>(); externalBanLists = new Dictionary <string, BanList>(); foreach (var i in config.GetValues("ExternalBanList")) { Console.WriteLine("simpletorrent: ExternalBanList {0}", i); externalBanList.Add(i); } externalBanListLimit = config.GetValueInt("ExternalBanListLimit"); if (externalBanListLimit.HasValue) { Console.WriteLine("simpletorrent: ExternalBanListLimit {0}", externalBanListLimit.Value); } EngineSettings engineSettings = new EngineSettings(downloadsPath, torrentListenPort.Value); engineSettings.PreferEncryption = true; engineSettings.AllowedEncryption = requireProtocolEncryption ? EncryptionTypes.RC4Full : EncryptionTypes.All; engineSettings.GlobalMaxConnections = 500; torrentDefaults = new TorrentSettings(4, 500, 0, 0); engine = new ClientEngine(engineSettings); engine.ChangeListenEndpoint(new IPEndPoint(IPAddress.Any, torrentListenPort.Value)); byte[] nodes = null; try { nodes = File.ReadAllBytes(dhtNodeFile); } catch { Console.WriteLine("simpletorrent: No existing DHT nodes could be loaded"); } dhtListner = new DhtListener(new IPEndPoint(IPAddress.Any, torrentListenPort.Value)); DhtEngine dht = new DhtEngine(dhtListner); engine.RegisterDht(dht); dhtListner.Start(); engine.DhtEngine.Start(nodes); foreach (var torrent in Directory.GetFiles(torrentsPath, "*.torrent")) { Torrent t = Torrent.Load(torrent); if (engine.Torrents.Where(i => i.InfoHash == t.InfoHash).Count() == 0) { TorrentManager tm = new TorrentManager(t, downloadsPath, torrentDefaults); engine.Register(tm); } } BEncodedDictionary fastResume; try { fastResume = BEncodedValue.Decode <BEncodedDictionary>(File.ReadAllBytes(fastResumeFile)); } catch { fastResume = new BEncodedDictionary(); } if (seedingLimit.HasValue) { Console.WriteLine("simpletorrent: Starting seeding limits watchdog timer..."); seedingLimitTimer = new System.Timers.Timer(); seedingLimitTimer.AutoReset = true; seedingLimitTimer.Interval = 60 * 1000; seedingLimitTimer.Elapsed += (s, e) => { lock (seedingLimitTorrents) { var torrentsToRemove = seedingLimitTorrents.Where(a => (DateTime.Now - a.Item1).TotalSeconds >= seedingLimit).ToArray(); foreach (var i in torrentsToRemove) { try { seedingLimitTorrents.Remove(i); if (i != null && i.Item2.State == TorrentState.Seeding) { Console.WriteLine("simpletorrent: Automatically removing \"{0}\"...", i.Item2.Torrent.Name); torrentInformation[i.Item2.InfoHash.ToHex()].ToRemove = "delete-torrent"; i.Item2.Stop(); } } catch { } } } }; seedingLimitTimer.Start(); } //Ban List System UpdateBanLists(); engine.ConnectionManager.BanPeer += (s, e) => { bool ban = false; lock (externalBanLists) { foreach (var i in externalBanLists) { ban |= i.Value.IsBanned(IPAddress.Parse(e.Peer.ConnectionUri.Host)); } } e.BanPeer = ban; if (e.BanPeer) { debugWriter.WriteLine(string.Format("Connection from {0} denied.", e.Peer.ConnectionUri.Host)); } else { debugWriter.WriteLine(string.Format("Connection from {0} allowed.", e.Peer.ConnectionUri.Host)); } }; if (externalBanListLimit.HasValue) { Console.WriteLine("simpletorrent: Starting external ban list update timer..."); externalBanListLimitTimer = new System.Timers.Timer(); externalBanListLimitTimer.AutoReset = true; externalBanListLimitTimer.Interval = 1000 * externalBanListLimit.Value; externalBanListLimitTimer.Elapsed += (s, e) => { UpdateBanLists(); }; externalBanListLimitTimer.Start(); } using (var httpServer = new HttpServer(new HttpRequestProvider())) { Console.WriteLine("simpletorrent: Starting HTTP(S) server..."); bool listeningOne = false; Console.WriteLine("simpletorrent: Creating session manager..."); httpServer.Use(new SessionHandler <SimpleTorrentSession>(() => new SimpleTorrentSession(), sessionLimit)); foreach (var ip in config.GetValues("Listen")) { try { TcpListener tl = getTcpListener(ip); httpServer.Use(new TcpListenerAdapter(tl)); Console.WriteLine("simpletorrent: Listening for HTTP on {0}...", tl.LocalEndpoint); listeningOne = true; } catch (Exception ex) { Console.WriteLine("simpletorrent: ({0}) " + ex.Message, ip); } } System.Security.Cryptography.X509Certificates.X509Certificate2 cert = null; if (config.HasValue("ListenSsl")) { cert = SSLSelfSigned.GetCertOrGenerate(sslCertificatePath, useECDSA); } foreach (var ip in config.GetValues("ListenSsl")) { try { TcpListener tl = getTcpListener(ip); //Mono does not support TLS 1.1 or 1.2 --> #if MONO httpServer.Use(new ListenerSslDecorator(new TcpListenerAdapter(tl), cert, System.Security.Authentication.SslProtocols.Ssl3 | System.Security.Authentication.SslProtocols.Tls)); #else //Force new systems to use TLS 1.1 or 1.2 httpServer.Use(new ListenerSslDecorator(new TcpListenerAdapter(tl), cert, System.Security.Authentication.SslProtocols.Tls11 | System.Security.Authentication.SslProtocols.Tls12)); #endif Console.WriteLine("simpletorrent: Listening for HTTPS on {0}...", tl.LocalEndpoint); listeningOne = true; } catch (Exception ex) { Console.WriteLine("simpletorrent: ({0}) " + ex.Message, ip); } } if (!listeningOne) { throw new SimpleTorrentException("simpletorrent was unable to bind to a single port."); } Console.WriteLine("simpletorrent: Running..."); httpServer.Use((context, next) => { context.Response = ProcessRequest(context); return(Task.Factory.GetCompleted()); }); foreach (var tm in engine.Torrents) { SetupTorrent(tm); } httpServer.Start(); Console.ReadLine(); } }
void Start() { //Start Torrent Engine torrents = new List<TorrentManager>(); messages = new List<SimpleMessage>(); //Torrents to remove seedingLimitTorrents = new List<Tuple<DateTime, TorrentManager>>(); Console.WriteLine("simpletorrent: version {0}", VERSION); Console.WriteLine("simpletorrent: Reading configuration file (simple.cfg)..."); config = new SimpleConfiguration("simple.cfg"); string basePath = Path.GetDirectoryName(System.Reflection.Assembly.GetEntryAssembly().Location); Console.WriteLine("simpletorrent: ApplicationPath (derived) {0}", basePath); if (config.HasValue("Debug")) { debugWriter = new DebugWriter(true); Console.WriteLine("simpletorrent: Debugging Enabled!"); } else { debugWriter = new DebugWriter(false); } PlatformID os = Environment.OSVersion.Platform; if (os == PlatformID.MacOSX) { Console.WriteLine("simpletorrent: We think we're on MacOSX"); simpleOperatingSystem = SimpleTorrentOperatingMode.MacOSX; } else if (os == PlatformID.Unix) { Console.WriteLine("simpletorrent: We think we're on *nix"); simpleOperatingSystem = SimpleTorrentOperatingMode.StarNix; } else { Console.WriteLine("simpletorrent: We think we're on Windows"); simpleOperatingSystem = SimpleTorrentOperatingMode.Windows; } torrentsPath = Path.GetFullPath(config.GetValue("TorrentPath", Path.Combine(basePath, "Torrents"))); downloadsPath = Path.GetFullPath(config.GetValue("DownloadPath", Path.Combine(basePath, "Downloads"))); sslCertificatePath = Path.GetFullPath(config.GetValue("SslCertificatePath", Path.Combine(basePath, "simple.pfx"))); useECDSA = config.HasValue("SslCertificateECDSA"); fastResumeFile = Path.Combine(torrentsPath, "fastresume.data"); dhtNodeFile = Path.Combine(torrentsPath, "dht.data"); requireProtocolEncryption = config.HasValue("RequireProtocolEncryption"); sessionLimit = config.GetValueInt("SessionLimit", 20); seedingLimit = config.GetValueInt("SeedingLimit"); // If the SavePath does not exist, we want to create it. if (!Directory.Exists(downloadsPath)) Directory.CreateDirectory(downloadsPath); // If the torrentsPath does not exist, we want to create it if (!Directory.Exists(torrentsPath)) Directory.CreateDirectory(torrentsPath); downloadsPathDrive = null; string myRootPath = Path.GetPathRoot(downloadsPath).ToLower(); if (simpleOperatingSystem == SimpleTorrentOperatingMode.StarNix) { System.Diagnostics.Process proc = new System.Diagnostics.Process(); proc.EnableRaisingEvents = false; proc.StartInfo.FileName = "bash"; proc.StartInfo.Arguments = "-c \"df -h " + downloadsPath + " | awk '{print $6}' | tail -1\""; proc.StartInfo.UseShellExecute = false; proc.StartInfo.RedirectStandardOutput = true; proc.Start(); string output = proc.StandardOutput.ReadToEnd().Trim().ToLower(); proc.WaitForExit(); if (proc.ExitCode == 0) { myRootPath = output; debugWriter.WriteLine("*nix override (bash -c 'df -h <path>') - \"" + output + "\""); } } else if (simpleOperatingSystem == SimpleTorrentOperatingMode.MacOSX) { System.Diagnostics.Process proc = new System.Diagnostics.Process(); proc.EnableRaisingEvents = false; proc.StartInfo.FileName = "bash"; proc.StartInfo.Arguments = "-c \"df -h " + downloadsPath + " | awk '{print $9}' | tail -1\""; proc.StartInfo.UseShellExecute = false; proc.StartInfo.RedirectStandardOutput = true; proc.Start(); string output = proc.StandardOutput.ReadToEnd().Trim().ToLower(); proc.WaitForExit(); if (proc.ExitCode == 0) { myRootPath = output; debugWriter.WriteLine("*nix override (bash -c 'df -h <path>') - \"" + output + "\""); } } foreach (var drive in DriveInfo.GetDrives()) { debugWriter.WriteLine("Enemerating Drives - " + drive.RootDirectory.FullName.ToString()); if (drive.RootDirectory.FullName.ToLower() == myRootPath) { downloadsPathDrive = drive; break; } } Console.WriteLine("simpletorrent: TorrentPath {0}", torrentsPath); Console.WriteLine("simpletorrent: DownloadPath {0}", downloadsPath); Console.WriteLine("simpletorrent: DownloadRootPath (derived) {0}", downloadsPathDrive); Console.WriteLine("simpletorrent: SslCertificatePath {0}", sslCertificatePath); Console.WriteLine("simpletorrent: SslCertificateECDSA {0}", useECDSA ? "Yes" : "No"); Console.WriteLine("simpletorrent: RequireProtocolEncryption {0}", requireProtocolEncryption ? "Yes" : "No"); Console.WriteLine("simpletorrent: SessionLimit {0}", sessionLimit); Console.WriteLine("simpletorrent: SeedingLimit {0}", seedingLimit.HasValue ? seedingLimit.Value.ToString() : "No"); int? torrentListenPort = config.GetValueInt("TorrentListenPort"); if (!torrentListenPort.HasValue) { throw new SimpleTorrentException("Configuration does not have a proper 'TorrentListenPort' value defined", null); } Console.WriteLine("simpletorrent: TorrentListenPort {0}", torrentListenPort); externalBanList = new List<string>(); externalBanLists = new Dictionary<string, BanList>(); foreach (var i in config.GetValues("ExternalBanList")) { Console.WriteLine("simpletorrent: ExternalBanList {0}", i); externalBanList.Add(i); } externalBanListLimit = config.GetValueInt("ExternalBanListLimit"); if (externalBanListLimit.HasValue) { Console.WriteLine("simpletorrent: ExternalBanListLimit {0}", externalBanListLimit.Value); } EngineSettings engineSettings = new EngineSettings(downloadsPath, torrentListenPort.Value); engineSettings.PreferEncryption = true; engineSettings.AllowedEncryption = requireProtocolEncryption ? EncryptionTypes.RC4Full : EncryptionTypes.All; engineSettings.GlobalMaxConnections = 500; torrentDefaults = new TorrentSettings(4, 500, 0, 0); engine = new ClientEngine(engineSettings); engine.ChangeListenEndpoint(new IPEndPoint(IPAddress.Any, torrentListenPort.Value)); byte[] nodes = null; try { nodes = File.ReadAllBytes(dhtNodeFile); } catch { Console.WriteLine("simpletorrent: No existing DHT nodes could be loaded"); } dhtListner = new DhtListener(new IPEndPoint(IPAddress.Any, torrentListenPort.Value)); DhtEngine dht = new DhtEngine(dhtListner); engine.RegisterDht(dht); dhtListner.Start(); engine.DhtEngine.Start(nodes); foreach (var torrent in Directory.GetFiles(torrentsPath, "*.torrent")) { Torrent t = Torrent.Load(torrent); if (engine.Torrents.Where(i => i.InfoHash == t.InfoHash).Count() == 0) { TorrentManager tm = new TorrentManager(t, downloadsPath, torrentDefaults); engine.Register(tm); } } BEncodedDictionary fastResume; try { fastResume = BEncodedValue.Decode<BEncodedDictionary>(File.ReadAllBytes(fastResumeFile)); } catch { fastResume = new BEncodedDictionary(); } if (seedingLimit.HasValue) { Console.WriteLine("simpletorrent: Starting seeding limits watchdog timer..."); seedingLimitTimer = new System.Timers.Timer(); seedingLimitTimer.AutoReset = true; seedingLimitTimer.Interval = 60 * 1000; seedingLimitTimer.Elapsed += (s, e) => { lock(seedingLimitTorrents) { var torrentsToRemove = seedingLimitTorrents.Where(a => (DateTime.Now - a.Item1).TotalSeconds >= seedingLimit).ToArray(); foreach (var i in torrentsToRemove) { try { seedingLimitTorrents.Remove(i); if (i != null && i.Item2.State == TorrentState.Seeding) { Console.WriteLine("simpletorrent: Automatically removing \"{0}\"...", i.Item2.Torrent.Name); torrentInformation[i.Item2.InfoHash.ToHex()].ToRemove = "delete-torrent"; i.Item2.Stop(); } } catch { } } } }; seedingLimitTimer.Start(); } //Ban List System UpdateBanLists(); engine.ConnectionManager.BanPeer += (s, e) => { bool ban = false; lock (externalBanLists) { foreach (var i in externalBanLists) { ban |= i.Value.IsBanned(IPAddress.Parse(e.Peer.ConnectionUri.Host)); } } e.BanPeer = ban; if (e.BanPeer) { debugWriter.WriteLine(string.Format("Connection from {0} denied.", e.Peer.ConnectionUri.Host)); } else { debugWriter.WriteLine(string.Format("Connection from {0} allowed.", e.Peer.ConnectionUri.Host)); } }; if (externalBanListLimit.HasValue) { Console.WriteLine("simpletorrent: Starting external ban list update timer..."); externalBanListLimitTimer = new System.Timers.Timer(); externalBanListLimitTimer.AutoReset = true; externalBanListLimitTimer.Interval = 1000 * externalBanListLimit.Value; externalBanListLimitTimer.Elapsed += (s, e) => { UpdateBanLists(); }; externalBanListLimitTimer.Start(); } using (var httpServer = new HttpServer(new HttpRequestProvider())) { Console.WriteLine("simpletorrent: Starting HTTP(S) server..."); bool listeningOne = false; Console.WriteLine("simpletorrent: Creating session manager..."); httpServer.Use(new SessionHandler<SimpleTorrentSession>(() => new SimpleTorrentSession(), sessionLimit)); foreach (var ip in config.GetValues("Listen")) { try { TcpListener tl = getTcpListener(ip); httpServer.Use(new TcpListenerAdapter(tl)); Console.WriteLine("simpletorrent: Listening for HTTP on {0}...", tl.LocalEndpoint); listeningOne = true; } catch (Exception ex) { Console.WriteLine("simpletorrent: ({0}) " + ex.Message, ip); } } System.Security.Cryptography.X509Certificates.X509Certificate2 cert = null; if (config.HasValue("ListenSsl")) { cert = SSLSelfSigned.GetCertOrGenerate(sslCertificatePath, useECDSA); } foreach (var ip in config.GetValues("ListenSsl")) { try { TcpListener tl = getTcpListener(ip); //Mono does not support TLS 1.1 or 1.2 --> #if MONO httpServer.Use(new ListenerSslDecorator(new TcpListenerAdapter(tl), cert, System.Security.Authentication.SslProtocols.Ssl3 | System.Security.Authentication.SslProtocols.Tls)); #else //Force new systems to use TLS 1.1 or 1.2 httpServer.Use(new ListenerSslDecorator(new TcpListenerAdapter(tl), cert, System.Security.Authentication.SslProtocols.Tls11 | System.Security.Authentication.SslProtocols.Tls12)); #endif Console.WriteLine("simpletorrent: Listening for HTTPS on {0}...", tl.LocalEndpoint); listeningOne = true; } catch (Exception ex) { Console.WriteLine("simpletorrent: ({0}) " + ex.Message, ip); } } if (!listeningOne) { throw new SimpleTorrentException("simpletorrent was unable to bind to a single port."); } Console.WriteLine("simpletorrent: Running..."); httpServer.Use((context, next) => { context.Response = ProcessRequest(context); return Task.Factory.GetCompleted(); }); foreach (var tm in engine.Torrents) { SetupTorrent(tm); } httpServer.Start(); Console.ReadLine(); } }