public async Task AnnounceUrl_Primary() { creator.Announce = "http://127.0.0.1:12345/announce"; BEncodedDictionary dict = await creator.CreateAsync("TorrentName", files); Assert.IsFalse(dict.ContainsKey("announce-list")); Assert.IsTrue(dict.ContainsKey("announce")); }
public async Task AnnounceUrl_None() { BEncodedDictionary dict = await creator.CreateAsync("TorrentName", files); Torrent t = Torrent.Load(dict); Assert.IsFalse(dict.ContainsKey("announce-list")); Assert.IsFalse(dict.ContainsKey("announce")); }
public override void Decode(byte[] buffer, int offset, int length) { peerDict = BEncodedValue.Decode<BEncodedDictionary>(buffer, offset, length, false); if (!peerDict.ContainsKey(AddedKey)) peerDict.Add(AddedKey, (BEncodedString)""); if (!peerDict.ContainsKey(AddedDotFKey)) peerDict.Add(AddedDotFKey, (BEncodedString)""); if (!peerDict.ContainsKey(DroppedKey)) peerDict.Add(DroppedKey, (BEncodedString)""); }
public async Task AnnounceUrl_ManyTiers() { foreach (var v in announces) { creator.Announces.Add(v); } BEncodedDictionary dict = await creator.CreateAsync("TorrentName", files); Assert.IsTrue(dict.ContainsKey("announce-list")); Assert.IsFalse(dict.ContainsKey("announce")); }
private static Peer DecodeFromDict(BEncodedDictionary dict) { string peerId; if (dict.ContainsKey("peer id")) peerId = dict["peer id"].ToString(); else if (dict.ContainsKey("peer_id")) // HACK: Some trackers return "peer_id" instead of "peer id" peerId = dict["peer_id"].ToString(); else peerId = string.Empty; Uri connectionUri = new Uri("tcp://" + dict["ip"].ToString() + ":" + dict["port"].ToString()); return new Peer(peerId, connectionUri, EncryptionTypes.All); }
public override void Decode(ReadOnlySpan <byte> buffer) { peerDict = ReadBencodedValue <BEncodedDictionary> (ref buffer, false); if (!peerDict.ContainsKey(AddedKey)) { peerDict.Add(AddedKey, BEncodedString.Empty); } if (!peerDict.ContainsKey(AddedDotFKey)) { peerDict.Add(AddedDotFKey, BEncodedString.Empty); } if (!peerDict.ContainsKey(DroppedKey)) { peerDict.Add(DroppedKey, BEncodedString.Empty); } }
public void Analys(out int deletedCount, out long cleanSize) { this._cleanSize = 0; UpdEventArgs args = new UpdEventArgs(); BEncodedDictionary resume = BEncodedValue.Decode <BEncodedDictionary>(File.ReadAllBytes(this._resumePath)); string[] torrentFilesList = Directory.GetFiles(this._torrentsPath, @"*.torrent", System.IO.SearchOption.TopDirectoryOnly); args.MaxProgress = torrentFilesList.Length; args.Progress = 0; args.DeletedCount = 0; this.UpdEvent(this, args); foreach (string file in torrentFilesList) { string fileName = Path.GetFileName(file); if (!resume.ContainsKey(new BEncodedString(fileName))) { this._cleanSize += GetFileSize(file); args.Msg = strings.DeletingFile.f(fileName); args.CleanSize = this._cleanSize; args.DeletedCount++; } args.Progress++; this.UpdEvent(this, args); } deletedCount = args.DeletedCount; cleanSize = args.CleanSize; }
public void Clean(bool moveToRecycle) { this._cleanSize = 0; UpdEventArgs args = new UpdEventArgs(); BEncodedDictionary resume = BEncodedValue.Decode <BEncodedDictionary>(File.ReadAllBytes(this._resumePath)); string[] torrentFilesList = Directory.GetFiles(this._torrentsPath, @"*.torrent", System.IO.SearchOption.TopDirectoryOnly); args.MaxProgress = torrentFilesList.Length; args.Progress = 0; args.DeletedCount = 0; this.UpdEvent(this, args); foreach (string file in torrentFilesList) { string fileName = Path.GetFileName(file); if (!resume.ContainsKey(new BEncodedString(fileName))) { RecycleOption ro = RecycleOption.DeletePermanently; if (moveToRecycle) { ro = RecycleOption.SendToRecycleBin; } this._cleanSize += GetFileSize(file); FileSystem.DeleteFile(file, UIOption.OnlyErrorDialogs, ro); args.Msg = strings.DeletingFile.f(fileName); args.CleanSize = this._cleanSize; args.DeletedCount++; } args.Progress++; this.UpdEvent(this, args); } }
public override void Decode(byte[] buffer, int offset, int length) { peerDict = BEncodedValue.Decode <BEncodedDictionary>(buffer, offset, length, false); if (!peerDict.ContainsKey(AddedKey)) { peerDict.Add(AddedKey, (BEncodedString)""); } if (!peerDict.ContainsKey(AddedDotFKey)) { peerDict.Add(AddedDotFKey, (BEncodedString)""); } if (!peerDict.ContainsKey(DroppedKey)) { peerDict.Add(DroppedKey, (BEncodedString)""); } }
internal FastResume(BEncodedDictionary dict) { CheckVersion(dict); CheckContent(dict, InfoHashKey); CheckContent(dict, BitfieldKey); CheckContent(dict, BitfieldLengthKey); // BEP52: Support backwards/forwards compatibility var infoHash = InfoHash.FromMemory(((BEncodedString)dict[InfoHashKey]).AsMemory()); if (infoHash.Span.Length == 20) { InfoHashes = InfoHashes.FromV1(infoHash); } else { InfoHashes = InfoHashes.FromV2(infoHash); } var data = ((BEncodedString)dict[BitfieldKey]).Span; Bitfield = new ReadOnlyBitField(data, (int)((BEncodedNumber)dict[BitfieldLengthKey]).Number); // If we're loading up an older version of the FastResume data then we if (dict.ContainsKey(UnhashedPiecesKey)) { data = ((BEncodedString)dict[UnhashedPiecesKey]).Span; UnhashedPieces = new ReadOnlyBitField(data, Bitfield.Length); } else { UnhashedPieces = new ReadOnlyBitField(Bitfield.Length); } }
static void CheckContent(BEncodedDictionary dict, BEncodedString key) { if (!dict.ContainsKey(key)) { throw new TorrentException($"Invalid FastResume data. Key '{key}' was not present"); } }
private void CheckContent(BEncodedDictionary dict, BEncodedString key) { if (!dict.ContainsKey(key)) { throw new TorrentException(string.Format("Invalid FastResume data. Key '{0}' was not present", key)); } }
void ScrapeReceived(IAsyncResult result) { string message = ""; object[] stateOb = (object[])result.AsyncState; WebRequest request = (WebRequest)stateOb[0]; object state = stateOb[1]; try { BEncodedDictionary d; BEncodedDictionary dict = DecodeResponse(request, result); // FIXME: Log the failure? if (!dict.ContainsKey("files")) { message = "Response contained no data"; return; } BEncodedDictionary files = (BEncodedDictionary)dict["files"]; foreach (KeyValuePair <BEncodedString, BEncodedValue> keypair in files) { d = (BEncodedDictionary)keypair.Value; foreach (KeyValuePair <BEncodedString, BEncodedValue> kp in d) { switch (kp.Key.ToString()) { case ("complete"): Complete = (int)((BEncodedNumber)kp.Value).Number; break; case ("downloaded"): Downloaded = (int)((BEncodedNumber)kp.Value).Number; break; case ("incomplete"): Incomplete = (int)((BEncodedNumber)kp.Value).Number; break; default: Logger.Log(null, "HttpTracker - Unknown scrape tag received: Key {0} Value {1}", kp.Key.ToString(), kp.Value.ToString()); break; } } } } catch (WebException) { message = "The tracker could not be contacted"; } catch { message = "The tracker returned an invalid or incomplete response"; } finally { RaiseScrapeComplete(new ScrapeResponseEventArgs(this, state, string.IsNullOrEmpty(message))); } }
public object Retrieve(string key) { if (!settings.ContainsKey(key)) { return(null); } return(this.settings[key]); }
//QUICKHACK: format bencoded val and get it back wereas must refactor tracker system to have more generic object... protected virtual void ReceiveAnnounce(AnnounceMessage announceMessage) { UdpTrackerMessage m; BEncodedDictionary dict = Handle(getCollection(announceMessage), endpoint.Address, false); if (dict.ContainsKey(RequestParameters.FailureKey)) { m = new ErrorMessage(announceMessage.TransactionId, dict[RequestParameters.FailureKey].ToString()); } else { TimeSpan interval = TimeSpan.Zero; int leechers = 0; int seeders = 0; List <System.Net.BitTorrent.Client.Peer> peers = new List <System.Net.BitTorrent.Client.Peer>(); foreach (KeyValuePair <BEncodedString, BEncodedValue> keypair in dict) { switch (keypair.Key.Text) { case ("complete"): seeders = Convert.ToInt32(keypair.Value.ToString()); //same as seeder? break; case ("incomplete"): leechers = Convert.ToInt32(keypair.Value.ToString()); //same as leecher? break; case ("interval"): interval = TimeSpan.FromSeconds(int.Parse(keypair.Value.ToString())); break; case ("peers"): if (keypair.Value is BEncodedList) // Non-compact response { peers.AddRange(System.Net.BitTorrent.Client.Peer.Decode((BEncodedList)keypair.Value)); } else if (keypair.Value is BEncodedString) // Compact response { peers.AddRange(System.Net.BitTorrent.Client.Peer.Decode((BEncodedString)keypair.Value)); } break; default: break; } } m = new AnnounceResponseMessage(announceMessage.TransactionId, interval, leechers, seeders, peers); } byte[] data = m.Encode(); #if NETSTANDARD1_5 listener.SendAsync(data, data.Length, endpoint); #else listener.Send(data, data.Length, endpoint); #endif }
protected virtual async Task ReceiveScrape(UdpClient client, ScrapeMessage scrapeMessage, IPEndPoint remotePeer) { BEncodedDictionary val = Handle(getCollection(scrapeMessage), remotePeer.Address, true); UdpTrackerMessage m; byte[] data; if (val.ContainsKey(TrackerRequest.FailureKey)) { m = new ErrorMessage(scrapeMessage.TransactionId, val[TrackerRequest.FailureKey].ToString()); } else { var scrapes = new List <ScrapeDetails> (); foreach (KeyValuePair <BEncodedString, BEncodedValue> keypair in val) { var dict = (BEncodedDictionary)keypair.Value; int seeds = 0; int leeches = 0; int complete = 0; foreach (KeyValuePair <BEncodedString, BEncodedValue> keypair2 in dict) { switch (keypair2.Key.Text) { case "complete": //The current number of connected seeds seeds = Convert.ToInt32(keypair2.Value.ToString()); break; case "downloaded": //The total number of completed downloads complete = Convert.ToInt32(keypair2.Value.ToString()); break; case "incomplete": leeches = Convert.ToInt32(keypair2.Value.ToString()); break; } } var sd = new ScrapeDetails(seeds, leeches, complete); scrapes.Add(sd); if (scrapes.Count == 74)//protocole do not support to send more than 74 scrape at once... { m = new ScrapeResponseMessage(scrapeMessage.TransactionId, scrapes); data = m.Encode(); await client.SendAsync(data, data.Length, remotePeer); scrapes.Clear(); } } m = new ScrapeResponseMessage(scrapeMessage.TransactionId, scrapes); } data = m.Encode(); await client.SendAsync(data, data.Length, remotePeer); }
static void Set(BEncodedDictionary dictionary, BEncodedString key, BEncodedValue value) { if (dictionary.ContainsKey(key)) { dictionary[key] = value; } else { dictionary.Add(key, value); } }
private static Peer DecodeFromDict(BEncodedDictionary dict) { string peerId; if (dict.ContainsKey("peer id")) { peerId = dict["peer id"].ToString(); } else if (dict.ContainsKey("peer_id")) // HACK: Some trackers return "peer_id" instead of "peer id" { peerId = dict["peer_id"].ToString(); } else { peerId = string.Empty; } Uri connectionUri = new Uri("tcp://" + dict["ip"] + ":" + dict["port"]); return(new Peer(peerId, connectionUri)); }
static Peer DecodeFromDict(BEncodedDictionary dict) { BEncodedString peerId; if (dict.ContainsKey("peer id")) { peerId = (BEncodedString)dict["peer id"]; } else if (dict.ContainsKey("peer_id")) // HACK: Some trackers return "peer_id" instead of "peer id" { peerId = (BEncodedString)dict["peer_id"]; } else { peerId = BEncodedString.Empty; } var connectionUri = new Uri($"ipv4://{dict["ip"]}:{dict["port"]}"); return(new Peer(peerId, connectionUri, EncryptionTypes.All)); }
static PeerInfo DecodeFromDict(BEncodedDictionary dict) { BEncodedString peerId; if (dict.ContainsKey(PeerIdKey)) { peerId = (BEncodedString)dict[PeerIdKey]; } else if (dict.ContainsKey(Peer_IdKey)) // HACK: Some trackers return "peer_id" instead of "peer id" { peerId = (BEncodedString)dict[Peer_IdKey]; } else { peerId = BEncodedString.Empty; } var connectionUri = new Uri($"ipv4://{dict[IPKey]}:{dict[PortKey]}"); return(new PeerInfo(connectionUri, peerId.AsMemory())); }
//QUICKHACK: format bencoded val and get it back wereas must refactor tracker system to have more generic object... protected virtual async Task ReceiveAnnounce(UdpClient client, AnnounceMessage announceMessage, IPEndPoint remotePeer) { UdpTrackerMessage m; BEncodedDictionary dict = Handle(getCollection(announceMessage), remotePeer.Address, false); if (dict.ContainsKey(TrackerRequest.FailureKey)) { m = new ErrorMessage(announceMessage.TransactionId, dict[TrackerRequest.FailureKey].ToString()); } else { TimeSpan interval = TimeSpan.Zero; int leechers = 0; int seeders = 0; var peers = new List <MonoTorrent.Client.Peer> (); foreach (KeyValuePair <BEncodedString, BEncodedValue> keypair in dict) { switch (keypair.Key.Text) { case ("complete"): seeders = Convert.ToInt32(keypair.Value.ToString()); //same as seeder? break; case ("incomplete"): leechers = Convert.ToInt32(keypair.Value.ToString()); //same as leecher? break; case ("interval"): interval = TimeSpan.FromSeconds(int.Parse(keypair.Value.ToString())); break; case ("peers"): if (keypair.Value is BEncodedList) // Non-compact response { peers.AddRange(MonoTorrent.Client.Peer.Decode((BEncodedList)keypair.Value)); } else if (keypair.Value is BEncodedString) // Compact response { peers.AddRange(MonoTorrent.Client.Peer.Decode((BEncodedString)keypair.Value)); } break; default: break; } } m = new AnnounceResponseMessage(announceMessage.TransactionId, interval, leechers, seeders, peers); } byte[] data = m.Encode(); await client.SendAsync(data, data.Length, remotePeer); }
async Task ScrapeReceivedAsync(InfoHash infoHash, WebResponse response) { try { await MainLoop.SwitchToThreadpool(); BEncodedDictionary dict = await DecodeResponseAsync(response).ConfigureAwait(false); // FIXME: Log the failure? if (!dict.ContainsKey("files")) { return; } BEncodedDictionary files = (BEncodedDictionary)dict["files"]; if (files.Count != 1) { throw new TrackerException("The scrape response contained unexpected data"); } var d = (BEncodedDictionary)files[new BEncodedString(infoHash.Hash)]; foreach (KeyValuePair <BEncodedString, BEncodedValue> kp in d) { switch (kp.Key.ToString()) { case ("complete"): Complete = (int)((BEncodedNumber)kp.Value).Number; break; case ("downloaded"): Downloaded = (int)((BEncodedNumber)kp.Value).Number; break; case ("incomplete"): Incomplete = (int)((BEncodedNumber)kp.Value).Number; break; default: Logger.Log(null, "HttpTracker - Unknown scrape tag received: Key {0} Value {1}", kp.Key.ToString(), kp.Value.ToString()); break; } } } catch (WebException) { throw; } catch { throw; } }
async ReusableTask <ScrapeResponse> ScrapeReceivedAsync(InfoHash infoHash, HttpResponseMessage response) { await new ThreadSwitcher(); int?complete = null, downloaded = null, incomplete = null; BEncodedDictionary dict = await DecodeResponseAsync(response).ConfigureAwait(false); // FIXME: Log the failure? if (!dict.ContainsKey("files")) { return(new ScrapeResponse(TrackerState.Ok, warningMessage: "Tracker did not have data for this torrent")); } var files = (BEncodedDictionary)dict["files"]; if (files.Count != 1) { throw new TrackerException("The scrape response contained unexpected data"); } var d = (BEncodedDictionary)files[new BEncodedString(infoHash.Span.ToArray())]; foreach (KeyValuePair <BEncodedString, BEncodedValue> kp in d) { switch (kp.Key.ToString()) { case "complete": complete = (int)((BEncodedNumber)kp.Value).Number; break; case "downloaded": downloaded = (int)((BEncodedNumber)kp.Value).Number; break; case "incomplete": incomplete = (int)((BEncodedNumber)kp.Value).Number; break; default: logger.InfoFormatted("Unknown scrape tag received: Key {0} Value {1}", kp.Key, kp.Value); break; } } return(new ScrapeResponse(TrackerState.Ok, complete: complete, incomplete: incomplete, downloaded: downloaded)); }
public static bool TryNoTraceDecodeMessage(BEncodedDictionary dictionary, out DhtMessage message, out string error) { message = null; error = null; if (dictionary[MessageTypeKey].Equals(QueryMessage.QueryType)) { if (!queryDecoders.ContainsKey((BEncodedString)dictionary[QueryNameKey])) { error = ((BEncodedString)dictionary[QueryNameKey]).Text; return(false); } message = queryDecoders[(BEncodedString)dictionary[QueryNameKey]](dictionary); } else if (dictionary[MessageTypeKey].Equals(ErrorMessage.ErrorType)) { message = new ErrorMessage(dictionary); } else { QueryMessage query = new NoTraceMessage(); BEncodedString key = (BEncodedString)dictionary[TransactionIdKey]; try { message = query.ResponseCreator(dictionary, query); //BEncodedValue q; //if (message == null && dictionary.TryGetValue("q", out q)) //{ // error = q.ToString(); //} if (message == null && dictionary.ContainsKey("q")) { dictionary[MessageTypeKey] = QueryMessage.QueryType; TryNoTraceDecodeMessage(dictionary, out message, out error); } } catch (Exception ex) { error = ex.ToString(); } } return(error == null && message != null); }
public FastResume(BEncodedDictionary dict) { CheckContent(dict, VersionKey, (BEncodedNumber)1); CheckContent(dict, InfoHashKey); CheckContent(dict, BitfieldKey); CheckContent(dict, BitfieldLengthKey); infoHash = new InfoHash(((BEncodedString)dict[InfoHashKey]).TextBytes); bitfield = new BitField((int)((BEncodedNumber)dict[BitfieldLengthKey]).Number); byte[] data = ((BEncodedString)dict[BitfieldKey]).TextBytes; bitfield.FromArray(data, 0, data.Length); if (dict.ContainsKey(PrioritiesKey)) { var list = (BEncodedList)dict[PrioritiesKey]; priorities = list.Select(v => (Priority)((BEncodedNumber)v).Number).ToArray(); } }
public static bool TryDecodeMessage(BEncodedDictionary dictionary, out Message message, out string error) { message = null; error = null; if (!dictionary.ContainsKey(MessageTypeKey)) { return(false); } if (dictionary[MessageTypeKey].Equals(QueryMessage.QueryType)) { message = queryDecoders[(BEncodedString)dictionary[QueryNameKey]](dictionary); } else if (dictionary[MessageTypeKey].Equals(ErrorMessage.ErrorType)) { message = new ErrorMessage(dictionary); } else { QueryMessage query; BEncodedString key = (BEncodedString)dictionary[TransactionIdKey]; if (messages.TryGetValue(key, out query)) { messages.Remove(key); try { message = query.ResponseCreator(dictionary, query); } catch { error = "Response dictionary was invalid"; } } else { error = "Response had bad transaction ID"; } } return(error == null && message != null); }
internal void SeedTorrents(List <string> torrentPaths) { this.engineState = EngineState.Seeding; this.StartDht(this.engine, Properties.Settings.Default.listenPort); this.managers.Clear(); this.torrents.Clear(); this.torrentPaths = torrentPaths; string fastResumeFile = Path.Combine(this.parent.localAppDataFolder, "fastresume.data"); BEncodedDictionary fastResume; try { fastResume = BEncodedValue.Decode <BEncodedDictionary>(File.ReadAllBytes(fastResumeFile)); } catch { fastResume = new BEncodedDictionary(); } foreach (string filePath in torrentPaths) { Torrent torrent = null; try { torrent = Torrent.Load(filePath); } catch (Exception e) { Console.WriteLine(e); debug(e.ToString()); continue; } this.torrents.Add(torrent); Console.WriteLine(Properties.Settings.Default.seedRate); TorrentSettings settings = new TorrentSettings(10, 50, 0, this.engine.Settings.GlobalMaxUploadSpeed); TorrentManager manager = new TorrentManager(torrent, engine.Settings.SavePath, settings); if (fastResume.ContainsKey(torrent.InfoHash.ToHex())) { manager.LoadFastResume(new FastResume((BEncodedDictionary)fastResume[torrent.InfoHash.ToHex()])); } this.managers.Add(manager); this.engine.Register(manager); manager.PeerConnected += manager_PeerConnected; manager.TorrentStateChanged += checkIncomplete; manager.TrackerManager.Announce(); manager.Start(); } //this.engine.StartAll(); }
internal FastResume(BEncodedDictionary dict) { CheckVersion(dict); CheckContent(dict, InfoHashKey); CheckContent(dict, BitfieldKey); CheckContent(dict, BitfieldLengthKey); Infohash = new InfoHash(((BEncodedString)dict[InfoHashKey]).TextBytes); Bitfield = new BitField((int)((BEncodedNumber)dict[BitfieldLengthKey]).Number); byte[] data = ((BEncodedString)dict[BitfieldKey]).TextBytes; Bitfield.FromArray(data, 0); UnhashedPieces = new BitField(Bitfield.Length); // If we're loading up an older version of the FastResume data then we if (dict.ContainsKey(UnhashedPiecesKey)) { data = ((BEncodedString)dict[UnhashedPiecesKey]).TextBytes; UnhashedPieces.FromArray(data, 0); } }
internal FastResume(BEncodedDictionary dict) { CheckVersion(dict); CheckContent(dict, InfoHashKey); CheckContent(dict, BitfieldKey); CheckContent(dict, BitfieldLengthKey); Infohash = InfoHash.FromMemory(((BEncodedString)dict[InfoHashKey]).AsMemory()); var data = ((BEncodedString)dict[BitfieldKey]).Span; Bitfield = new BitField(data, (int)((BEncodedNumber)dict[BitfieldLengthKey]).Number); // If we're loading up an older version of the FastResume data then we if (dict.ContainsKey(UnhashedPiecesKey)) { data = ((BEncodedString)dict[UnhashedPiecesKey]).Span; UnhashedPieces = new BitField(data, Bitfield.Length); } else { UnhashedPieces = new BitField(Bitfield.Length); } }
static BEncodedValue Get(BEncodedDictionary dictionary, BEncodedString key) { return dictionary.ContainsKey(key) ? dictionary[key] : null; }
private static void CheckContent(BEncodedDictionary dict, BEncodedString key) { if (dict.ContainsKey(key) == false) throw new TorrentException(string.Format("Invalid FastResume data. Key '{0}' was not present", key)); }
private void CheckContent(BEncodedDictionary dict, BEncodedString key) { if (dict == null) throw new ArgumentNullException(nameof(dict)); if (!dict.ContainsKey(key)) throw new TorrentException(string.Format("Invalid FastResume data. Key '{0}' was not present", key)); }
public void InitializeTorrent(string torrentDir) { BEncodedDictionary fastResume; try { fastResume = BEncodedValue.Decode<BEncodedDictionary>(File.ReadAllBytes(this.fastResumeFile)); } catch { fastResume = new BEncodedDictionary(); } Torrent torrent = null; // Load the file into the engine if it ends with .torrent. if (torrentDir.EndsWith(".torrent")) { try { // Load the .torrent file from the file into a Torrent instance // You can use this to do preprocessing should you need to. torrent = Torrent.Load(torrentDir); Console.WriteLine(torrent.InfoHash.ToString()); } catch (Exception e) { Console.Write("Could not decode {0}: {1}", torrentDir, e.Message); return; } // When any preprocessing has been completed, you create a TorrentManager which you then register with the engine. TorrentManager postProcessManager = new TorrentManager(torrent, this.downloadDir, torrentDefaults); if (fastResume.ContainsKey(torrent.InfoHash.ToHex())) { postProcessManager.LoadFastResume(new FastResume((BEncodedDictionary)fastResume[torrent.InfoHash.ToHex()])); } this.clientEngine.Register(postProcessManager); // Store the torrent manager in our list so we can access it later. this.torrentManagers.Add(postProcessManager); postProcessManager.PeersFound += new EventHandler<PeersAddedEventArgs>(this.manager_PeersFound); } // For each torrent manager we loaded and stored in our list, hook into the events in the torrent manager and start the engine. foreach (TorrentManager torrentManager in this.torrentManagers) { // Every time a piece is hashed, this is fired. torrentManager.PieceHashed += delegate(object o, PieceHashedEventArgs e) { lock (this.topTrackers) { topTrackers.WriteLine(string.Format("Piece hashed: {0} - {1} ", e.PieceIndex, e.HashPassed ? "passed" : "failed")); } }; // Everytime the state changes (stopped -> seeding -> downloading -> hashing), this is fired. foreach (TrackerTier tier in torrentManager.TrackerManager) { List<Tracker> trackers = tier.GetTrackers(); foreach (Tracker tracker in trackers) { tracker.AnnounceComplete += delegate(object sender, AnnounceResponseEventArgs e) { this.topTrackers.WriteLine(string.Format("{0}: {1}", e.Successful, e.Tracker.ToString())); }; } } // Start the torrentManager. The file will then hash (if required) and begin loading. torrentManager.Start(); } Thread.Sleep(500); }
static void Set(BEncodedDictionary dictionary, BEncodedString key, BEncodedValue value) { if (dictionary.ContainsKey(key)) dictionary[key] = value; else dictionary.Add(key, value); }
/// <summary> /// This method is called internally to load the information found within the "Info" section /// of the .torrent file /// </summary> /// <param name="dictionary">The dictionary representing the Info section of the .torrent file</param> private void ProcessInfo(BEncodedDictionary dictionary) { metadata = dictionary.Encode(); this.pieceLength = int.Parse(dictionary["piece length"].ToString()); LoadHashPieces(((BEncodedString)dictionary["pieces"]).TextBytes); foreach (KeyValuePair <BEncodedString, BEncodedValue> keypair in dictionary) { switch (keypair.Key.Text) { case ("source"): this.source = keypair.Value.ToString(); break; case ("sha1"): this.sha1 = ((BEncodedString)keypair.Value).TextBytes; break; case ("ed2k"): this.ed2k = ((BEncodedString)keypair.Value).TextBytes; break; case ("publisher-url.utf-8"): if (keypair.Value.ToString().Length > 0) { this.publisherUrl = keypair.Value.ToString(); } break; case ("publisher-url"): if ((String.IsNullOrEmpty(publisherUrl)) && (keypair.Value.ToString().Length > 0)) { this.publisherUrl = keypair.Value.ToString(); } break; case ("publisher.utf-8"): if (keypair.Value.ToString().Length > 0) { this.publisher = keypair.Value.ToString(); } break; case ("publisher"): if ((String.IsNullOrEmpty(publisher)) && (keypair.Value.ToString().Length > 0)) { this.publisher = keypair.Value.ToString(); } break; case ("files"): LoadTorrentFiles(((BEncodedList)keypair.Value)); break; case ("name.utf-8"): if (keypair.Value.ToString().Length > 0) { this.name = keypair.Value.ToString(); } break; case ("name"): if ((String.IsNullOrEmpty(this.name)) && (keypair.Value.ToString().Length > 0)) { this.name = keypair.Value.ToString(); } break; case ("piece length"): // Already handled break; case ("length"): break; // This is a singlefile torrent case ("private"): this.isPrivate = (keypair.Value.ToString() == "1") ? true : false; break; default: break; } } if (this.torrentFiles == null) // Not a multi-file torrent { long length = long.Parse(dictionary["length"].ToString()); this.size = length; string path = this.name; byte[] md5 = (dictionary.ContainsKey("md5")) ? ((BEncodedString)dictionary["md5"]).TextBytes : null; byte[] ed2k = (dictionary.ContainsKey("ed2k")) ? ((BEncodedString)dictionary["ed2k"]).TextBytes : null; byte[] sha1 = (dictionary.ContainsKey("sha1")) ? ((BEncodedString)dictionary["sha1"]).TextBytes : null; this.torrentFiles = new TorrentFile[1]; int endPiece = Math.Min(Pieces.Count - 1, (int)((size + (pieceLength - 1)) / pieceLength)); this.torrentFiles[0] = new TorrentFile(path, length, path, 0, endPiece, 0, md5, ed2k, sha1); } }
private static void StartEngine() { int port; Torrent torrent = null; // Ask the user what port they want to use for incoming connections //Console.Write(Environment.NewLine + "Choose a listen port: "); //while (!Int32.TryParse(Console.ReadLine(), out port)) { } port = 4545; // Create the settings which the engine will use // downloadsPath - this is the path where we will save all the files to // port - this is the port we listen for connections on EngineSettings engineSettings = new EngineSettings(downloadsPath, port); engineSettings.PreferEncryption = false; engineSettings.AllowedEncryption = EncryptionTypes.All; //engineSettings.GlobalMaxUploadSpeed = 30 * 1024; //engineSettings.GlobalMaxDownloadSpeed = 100 * 1024; //engineSettings.MaxReadRate = 1 * 1024 * 1024; // Create the default settings which a torrent will have. // 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 TorrentSettings torrentDefaults = new TorrentSettings(4, 150, 0, 0); // Create an instance of the engine. engine = new ClientEngine(engineSettings); engine.ChangeListenEndpoint(new IPEndPoint(IPAddress.Any, port)); byte[] nodes = null; try { nodes = File.ReadAllBytes(dhtNodeFile); } catch { Console.WriteLine("No existing dht nodes could be loaded"); } DhtListener dhtListner = new DhtListener (new IPEndPoint (IPAddress.Any, port)); DhtEngine dht = new DhtEngine (dhtListner); engine.RegisterDht(dht); dhtListner.Start(); engine.DhtEngine.Start(nodes); // If the SavePath does not exist, we want to create it. if (!Directory.Exists(engine.Settings.SavePath)) Directory.CreateDirectory(engine.Settings.SavePath); // If the torrentsPath does not exist, we want to create it if (!Directory.Exists(torrentsPath)) Directory.CreateDirectory(torrentsPath); BEncodedDictionary fastResume; try { fastResume = BEncodedValue.Decode<BEncodedDictionary>(File.ReadAllBytes(fastResumeFile)); } catch { fastResume = new BEncodedDictionary(); } // For each file in the torrents path that is a .torrent file, load it into the engine. foreach (string file in Directory.GetFiles(torrentsPath)) { if (file.EndsWith(".torrent")) { try { // Load the .torrent from the file into a Torrent instance // You can use this to do preprocessing should you need to torrent = Torrent.Load(file); Console.WriteLine(torrent.InfoHash.ToString()); } catch (Exception e) { Console.Write("Couldn't decode {0}: ", file); Console.WriteLine(e.Message); continue; } // When any preprocessing has been completed, you create a TorrentManager // which you then register with the engine. TorrentManager manager = new TorrentManager(torrent, downloadsPath, torrentDefaults); if (fastResume.ContainsKey(torrent.InfoHash.ToHex ())) manager.LoadFastResume(new FastResume ((BEncodedDictionary)fastResume[torrent.InfoHash.ToHex ()])); engine.Register(manager); // Store the torrent manager in our list so we can access it later torrents.Add(manager); manager.PeersFound += new EventHandler<PeersAddedEventArgs>(manager_PeersFound); } } // If we loaded no torrents, just exist. The user can put files in the torrents directory and start // the client again if (torrents.Count == 0) { Console.WriteLine("No torrents found in the Torrents directory"); Console.WriteLine("Exiting..."); engine.Dispose(); return; } // For each torrent manager we loaded and stored in our list, hook into the events // in the torrent manager and start the engine. foreach (TorrentManager manager in torrents) { // Every time a piece is hashed, this is fired. manager.PieceHashed += delegate(object o, PieceHashedEventArgs e) { lock (listener) listener.WriteLine(string.Format("Piece Hashed: {0} - {1}", e.PieceIndex, e.HashPassed ? "Pass" : "Fail")); }; // Every time the state changes (Stopped -> Seeding -> Downloading -> Hashing) this is fired manager.TorrentStateChanged += delegate (object o, TorrentStateChangedEventArgs e) { lock (listener) listener.WriteLine("OldState: " + e.OldState.ToString() + " NewState: " + e.NewState.ToString()); }; // Every time the tracker's state changes, this is fired foreach (TrackerTier tier in manager.TrackerManager) { foreach (MonoTorrent.Client.Tracker.Tracker t in tier.Trackers) { t.AnnounceComplete += delegate(object sender, AnnounceResponseEventArgs e) { listener.WriteLine(string.Format("{0}: {1}", e.Successful, e.Tracker.ToString())); }; } } // Start the torrentmanager. The file will then hash (if required) and begin downloading/seeding manager.Start(); } // While the torrents are still running, print out some stats to the screen. // Details for all the loaded torrent managers are shown. int i = 0; bool running = true; StringBuilder sb = new StringBuilder(1024); while (running) { if ((i++) % 10 == 0) { sb.Remove(0, sb.Length); running = torrents.Exists(delegate(TorrentManager m) { return m.State != TorrentState.Stopped; }); AppendFormat(sb, "Total Download Rate: {0:0.00}kB/sec", engine.TotalDownloadSpeed / 1024.0); AppendFormat(sb, "Total Upload Rate: {0:0.00}kB/sec", engine.TotalUploadSpeed / 1024.0); AppendFormat(sb, "Disk Read Rate: {0:0.00} kB/s", engine.DiskManager.ReadRate / 1024.0); AppendFormat(sb, "Disk Write Rate: {0:0.00} kB/s", engine.DiskManager.WriteRate / 1024.0); AppendFormat(sb, "Total Read: {0:0.00} kB", engine.DiskManager.TotalRead / 1024.0); AppendFormat(sb, "Total Written: {0:0.00} kB", engine.DiskManager.TotalWritten / 1024.0); AppendFormat(sb, "Open Connections: {0}", engine.ConnectionManager.OpenConnections); foreach (TorrentManager manager in torrents) { AppendSeperator(sb); AppendFormat(sb, "State: {0}", manager.State); AppendFormat(sb, "Name: {0}", manager.Torrent == null ? "MetaDataMode" : manager.Torrent.Name); AppendFormat(sb, "Progress: {0:0.00}", manager.Progress); AppendFormat(sb, "Download Speed: {0:0.00} kB/s", manager.Monitor.DownloadSpeed / 1024.0); AppendFormat(sb, "Upload Speed: {0:0.00} kB/s", manager.Monitor.UploadSpeed / 1024.0); AppendFormat(sb, "Total Downloaded: {0:0.00} MB", manager.Monitor.DataBytesDownloaded / (1024.0 * 1024.0)); AppendFormat(sb, "Total Uploaded: {0:0.00} MB", manager.Monitor.DataBytesUploaded / (1024.0 * 1024.0)); MonoTorrent.Client.Tracker.Tracker tracker = manager.TrackerManager.CurrentTracker; //AppendFormat(sb, "Tracker Status: {0}", tracker == null ? "<no tracker>" : tracker.State.ToString()); AppendFormat(sb, "Warning Message: {0}", tracker == null ? "<no tracker>" : tracker.WarningMessage); AppendFormat(sb, "Failure Message: {0}", tracker == null ? "<no tracker>" : tracker.FailureMessage); if (manager.PieceManager != null) AppendFormat(sb, "Current Requests: {0}", manager.PieceManager.CurrentRequestCount()); foreach (PeerId p in manager.GetPeers()) { //CovertChannel.CovertChannel.targetPeerId = ; //CovertChannel.CovertPicker picker = new CovertChannel.CovertPicker (null); AppendFormat (sb, "\t{2} - {1:0.00}/{3:0.00}kB/sec - {0}", p.Peer.ConnectionUri, p.Monitor.DownloadSpeed / 1024.0, p.AmRequestingPiecesCount, p.Monitor.UploadSpeed / 1024.0); } AppendFormat(sb, "", null); if (manager.Torrent != null) foreach (TorrentFile file in manager.Torrent.Files) AppendFormat(sb, "{1:0.00}% - {0}", file.Path, file.BitField.PercentComplete); } //Console.Clear(); Console.WriteLine(sb.ToString()); listener.ExportTo(Console.Out); } System.Threading.Thread.Sleep(500); } }
protected void LoadInternal(BEncodedDictionary torrentInformation) { Check.TorrentInformation(torrentInformation); originalDictionary = torrentInformation; torrentPath = ""; try { foreach (KeyValuePair <BEncodedString, BEncodedValue> keypair in torrentInformation) { switch (keypair.Key.Text) { case ("announce"): // Ignore this if we have an announce-list if (torrentInformation.ContainsKey("announce-list")) { break; } announceUrls.Add(new RawTrackerTier()); announceUrls[0].Add(keypair.Value.ToString()); break; case ("creation date"): try { try { creationDate = creationDate.AddSeconds(long.Parse(keypair.Value.ToString())); } catch (Exception e) { if (e is ArgumentOutOfRangeException) { creationDate = creationDate.AddMilliseconds(long.Parse(keypair.Value.ToString())); } else { throw; } } } catch (Exception e) { if (e is ArgumentOutOfRangeException) { throw new BEncodingException("Argument out of range exception when adding seconds to creation date.", e); } else if (e is FormatException) { throw new BEncodingException(String.Format("Could not parse {0} into a number", keypair.Value), e); } else { throw; } } break; case ("nodes"): nodes = (BEncodedList)keypair.Value; break; case ("comment.utf-8"): if (keypair.Value.ToString().Length != 0) { comment = keypair.Value.ToString(); // Always take the UTF-8 version } break; // even if there's an existing value case ("comment"): if (String.IsNullOrEmpty(comment)) { comment = keypair.Value.ToString(); } break; case ("publisher-url.utf-8"): // Always take the UTF-8 version publisherUrl = keypair.Value.ToString(); // even if there's an existing value break; case ("publisher-url"): if (String.IsNullOrEmpty(publisherUrl)) { publisherUrl = keypair.Value.ToString(); } break; case ("azureus_properties"): azureusProperties = keypair.Value; break; case ("created by"): createdBy = keypair.Value.ToString(); break; case ("encoding"): encoding = keypair.Value.ToString(); break; case ("info"): using (SHA1 s = HashAlgoFactory.Create <SHA1>()) infoHash = new InfoHash(s.ComputeHash(keypair.Value.Encode())); ProcessInfo(((BEncodedDictionary)keypair.Value)); break; case ("name"): // Handled elsewhere break; case ("announce-list"): if (keypair.Value is BEncodedString) { break; } BEncodedList announces = (BEncodedList)keypair.Value; for (int j = 0; j < announces.Count; j++) { if (announces[j] is BEncodedList) { BEncodedList bencodedTier = (BEncodedList)announces[j]; List <string> tier = new List <string>(bencodedTier.Count); for (int k = 0; k < bencodedTier.Count; k++) { tier.Add(bencodedTier[k].ToString()); } Toolbox.Randomize <string>(tier); RawTrackerTier collection = new RawTrackerTier(); for (int k = 0; k < tier.Count; k++) { collection.Add(tier[k]); } if (collection.Count != 0) { announceUrls.Add(collection); } } else { throw new BEncodingException(String.Format("Non-BEncodedList found in announce-list (found {0})", announces[j].GetType())); } } break; case ("httpseeds"): // This form of web-seeding is not supported. break; case ("url-list"): if (keypair.Value is BEncodedString) { getRightHttpSeeds.Add(((BEncodedString)keypair.Value).Text); } else if (keypair.Value is BEncodedList) { foreach (BEncodedString str in (BEncodedList)keypair.Value) { GetRightHttpSeeds.Add(str.Text); } } break; default: break; } } } catch (Exception e) { if (e is BEncodingException) { throw; } else { throw new BEncodingException("", e); } } }
/// <summary> /// Fully starts the torrent engine and dht engine and listener /// Loads in any torrents from the directory and resumes them automaticallhy /// </summary> public void Initiate() { torrentEngine = new ClientEngine(engineSettings); torrentEngine.ChangeListenEndpoint(new IPEndPoint(IPAddress.Any, Port)); //Load DHT nodes from a saved file //if not there or any errors then continue byte[] nodes = null; try { nodes = File.ReadAllBytes(dhtNodeFile); } catch { //keep it null, what we use it for will instead create its own and then save them nodes = null; } //construct our listener for our dht engine and then create the dht engine //register it and then start it based on the nodes we attempted to load //construct our listener for our dht engine and then create the dht engine //register it and then start it based on the nodes we attempted to load dhtListener = new DhtListener(new IPEndPoint(IPAddress.Any, Port)); dhtEngine = new DhtEngine(dhtListener); torrentEngine.RegisterDht(dhtEngine); torrentEngine.DhtEngine.Start(nodes); //same as with the dht nodes try to load but if any errors then continue try { fastResume = BEncodedValue.Decode<BEncodedDictionary>(File.ReadAllBytes(resumeFile)); } catch { fastResume = new BEncodedDictionary(); } //This is where we go into our save directory and look for any torrents //user may of left off on a download and we can possibly resume it //also a backend way to force a download from another provider source to download foreach (string file in Directory.GetFiles(saveDirectory)) { if (file.EndsWith(".torrent")) { try { Torrent torrent = null; torrent = Torrent.Load(file); TorrentManager manager = new TorrentManager(torrent, saveDirectory, torrentSettings); if (fastResume.ContainsKey(torrent.InfoHash.ToHex())) manager.LoadFastResume(new FastResume((BEncodedDictionary)fastResume[torrent.InfoHash.ToHex()])); torrentEngine.Register(manager); } catch { } } } }