public void benNumberDecoding() { byte[] data = Encoding.UTF8.GetBytes("i12412e"); using Stream stream = new MemoryStream(data); BEncodedValue result = BEncodedValue.Decode(stream); Assert.AreEqual(result is BEncodedNumber, true); Assert.AreEqual(result.ToString(), "12412"); Assert.AreEqual(((BEncodedNumber)result).Number, 12412); }
public void benDictionaryStackedTest() { string benString = "d4:testd5:testsli12345ei12345ee2:tod3:tomi12345eeee"; byte[] data = Encoding.UTF8.GetBytes(benString); BEncodedDictionary dict = (BEncodedDictionary)BEncodedValue.Decode(data); string decoded = Encoding.UTF8.GetString(dict.Encode()); Assert.AreEqual(benString, decoded); }
public void benListStackedTest() { const string benString = "l6:stringl7:stringsl8:stringedei23456eei12345ee"; var data = Encoding.UTF8.GetBytes(benString); var list = (BEncodedList)BEncodedValue.Decode(data); var decoded = Encoding.UTF8.GetString(list.Encode()); Assert.AreEqual(benString, decoded); }
public void benListStackedTest() { string benString = "l6:stringl7:stringsl8:stringedei23456eei12345ee"; byte[] data = System.Text.Encoding.UTF8.GetBytes(benString); BEncodedList list = (BEncodedList)BEncodedValue.Decode(data); string decoded = System.Text.Encoding.UTF8.GetString(list.Encode()); Assert.AreEqual(benString, decoded); }
public void benStringDecoding() { byte[] data = Encoding.UTF8.GetBytes("21:this is a test string"); using MemoryStream stream = new MemoryStream(data); BEncodedValue result = BEncodedValue.Decode(stream); Assert.AreEqual("this is a test string", result.ToString()); Assert.AreEqual(result is BEncodedString, true); Assert.AreEqual(((BEncodedString)result).Text, "this is a test string"); }
public void PingTimeout() { bool pingSuccessful = false; var ping = new Ping(node.Id) { TransactionId = transactionId }; bool timedOutPingSuccessful = false; var timedOutPing = new Ping(node.Id) { TransactionId = (BEncodedNumber)5 }; listener.MessageSent += (data, endpoint) => { engine.MessageLoop.DhtMessageFactory.TryDecodeMessage(BEncodedValue.Decode <BEncodedDictionary> (data), out DhtMessage message); if (message.TransactionId.Equals(ping.TransactionId)) { var response = new PingResponse(node.Id, transactionId); listener.RaiseMessageReceived(response, endpoint); } }; engine.MessageLoop.QuerySent += (o, e) => { // This ping should not time out. if (e.Query.TransactionId.Equals(ping.TransactionId)) { pingSuccessful = !e.TimedOut; } // This ping should time out. if (e.Query.TransactionId.Equals(timedOutPing.TransactionId)) { timedOutPingSuccessful = e.TimedOut; } }; // Send the ping which will be responded to Assert.IsTrue(engine.SendQueryAsync(ping, node).Wait(1000), "#0a"); Assert.AreEqual(0, node.FailedCount, "#0b"); engine.MessageLoop.Timeout = TimeSpan.Zero; node.Seen(TimeSpan.FromHours(1)); // Send a ping which will time out Assert.IsTrue(engine.SendQueryAsync(timedOutPing, node).Wait(1000), "#0c"); Assert.AreEqual(4, node.FailedCount, "#1"); Assert.AreEqual(NodeState.Bad, node.State, "#2"); Assert.IsTrue(node.LastSeen >= TimeSpan.FromHours(1), "#3"); Assert.IsTrue(pingSuccessful, "#4"); Assert.IsTrue(pingSuccessful, "#5"); }
/// <summary> /// Called from either Load(stream) or Load(string). /// </summary> /// <param name="stream"></param> /// <param name="path"></param> /// <returns></returns> static Torrent Load(Stream stream, string path) { Check.Stream(stream); Check.Path(path); try { return(LoadCore((BEncodedDictionary)BEncodedValue.Decode(stream))); } catch (BEncodingException ex) { throw new TorrentException("Invalid torrent file specified", ex); } }
static T Deserialize <T> (byte[] array) where T : new() { T builder = new T(); var dict = (BEncodedDictionary)BEncodedValue.Decode(array); var props = builder.GetType().GetProperties(); foreach (var property in props) { if (!dict.TryGetValue(property.Name, out BEncodedValue value)) { continue; } if (property.PropertyType == typeof(bool)) { property.SetValue(builder, bool.Parse(value.ToString())); } else if (property.PropertyType == typeof(string)) { property.SetValue(builder, ((BEncodedString)value).Text); } else if (property.PropertyType == typeof(FastResumeMode)) { property.SetValue(builder, Enum.Parse(typeof(FastResumeMode), ((BEncodedString)value).Text)); } else if (property.PropertyType == typeof(TimeSpan)) { property.SetValue(builder, TimeSpan.FromTicks(((BEncodedNumber)value).Number)); } else if (property.PropertyType == typeof(int)) { property.SetValue(builder, (int)((BEncodedNumber)value).Number); } else if (property.PropertyType == typeof(IPAddress)) { property.SetValue(builder, IPAddress.Parse(((BEncodedString)value).Text)); } else if (property.PropertyType == typeof(IList <EncryptionType>)) { var list = (IList <EncryptionType>)property.GetValue(builder); list.Clear(); foreach (BEncodedString encryptionType in (BEncodedList)value) { list.Add((EncryptionType)Enum.Parse(typeof(EncryptionType), encryptionType.Text)); } } else { throw new NotSupportedException($"{property.Name} => type: ${property.PropertyType}"); } } return(builder); }
public async Task BucketRefreshTest() { List <Node> nodes = new List <Node> (); for (int i = 0; i < 5; i++) { nodes.Add(new Node(NodeId.Create(), new IPEndPoint(IPAddress.Any, i))); } listener.MessageSent += (data, endpoint) => { engine.MessageLoop.DhtMessageFactory.TryDecodeMessage(BEncodedValue.Decode <BEncodedDictionary> (data), out DhtMessage message); Node current = nodes.Find(n => n.EndPoint.Port.Equals(endpoint.Port)); if (current == null) { return; } if (message is Ping) { PingResponse r = new PingResponse(current.Id, message.TransactionId); listener.RaiseMessageReceived(r, current.EndPoint); } else if (message is FindNode) { FindNodeResponse response = new FindNodeResponse(current.Id, message.TransactionId); response.Nodes = ""; listener.RaiseMessageReceived(response, current.EndPoint); } }; foreach (var n in nodes) { engine.RoutingTable.Add(n); } foreach (Bucket b in engine.RoutingTable.Buckets) { b.Changed(TimeSpan.FromDays(1)); foreach (var n in b.Nodes) { n.Seen(TimeSpan.FromDays(1)); } } await engine.RefreshBuckets(); foreach (Bucket b in engine.RoutingTable.Buckets) { Assert.IsTrue(b.LastChanged < TimeSpan.FromHours(1)); Assert.IsTrue(b.Nodes.Exists(n => n.LastSeen < TimeSpan.FromHours(1))); } }
public void GetSeedTest() { SeedCargo cargo = new SeedCargo(); SHA1 sha1 = SHA1.Create(); byte[] buffer = File.ReadAllBytes("test.torrent"); var hash = sha1.ComputeHash(buffer); var info = BEncodedValue.Decode <BEncodedDictionary>(buffer); cargo.Add(info, hash); Assert.IsTrue(cargo.GetSeed(hash).Infohash.SequenceEqual(hash)); }
public bool TryGetFastResume(string fastResumePath) { try { FastResume = BEncodedValue.Decode <BEncodedDictionary>(File.ReadAllBytes(fastResumePath)); } catch { FastResume = new BEncodedDictionary(); } return(FastResume.Count > 0); }
internal Torrent GetTorrent() { byte[] calculatedInfoHash; using (SHA1 sha = HashAlgoFactory.Create<SHA1>()) calculatedInfoHash = sha.ComputeHash(stream.ToArray()); if (!Manager.InfoHash.Equals (calculatedInfoHash)) throw new Exception("invalid metadata");//restart ? BEncodedValue d = BEncodedValue.Decode(stream); BEncodedDictionary dict = new BEncodedDictionary(); dict.Add("info", d); return Torrent.LoadCore(dict); }
public static async Task <ClientEngine> RestoreStateAsync(ReadOnlyMemory <byte> buffer) { var state = BEncodedValue.Decode <BEncodedDictionary> (buffer.Span); var engineSettings = Serializer.DeserializeEngineSettings((BEncodedDictionary)state["Settings"]); var clientEngine = new ClientEngine(engineSettings); TorrentManager manager; foreach (BEncodedDictionary torrent in (BEncodedList)state[nameof(clientEngine.Torrents)]) { var saveDirectory = ((BEncodedString)torrent[nameof(manager.SavePath)]).Text; var streaming = bool.Parse(((BEncodedString)torrent["Streaming"]).Text); var torrentSettings = Serializer.DeserializeTorrentSettings((BEncodedDictionary)torrent[nameof(manager.Settings)]); if (torrent.ContainsKey(nameof(manager.MetadataPath))) { var metadataPath = (BEncodedString)torrent[nameof(manager.MetadataPath)]; if (streaming) { manager = await clientEngine.AddStreamingAsync(metadataPath.Text, saveDirectory, torrentSettings); } else { manager = await clientEngine.AddAsync(metadataPath.Text, saveDirectory, torrentSettings); } foreach (BEncodedDictionary file in (BEncodedList)torrent[nameof(manager.Files)]) { TorrentFileInfo torrentFile; torrentFile = (TorrentFileInfo)manager.Files.Single(t => t.Path == ((BEncodedString)file[nameof(torrentFile.Path)]).Text); torrentFile.Priority = (Priority)Enum.Parse(typeof(Priority), file[nameof(torrentFile.Priority)].ToString()); torrentFile.FullPath = ((BEncodedString)file[nameof(torrentFile.FullPath)]).Text; } } else { var magnetLink = MagnetLink.Parse(torrent[nameof(manager.MagnetLink)].ToString()); if (streaming) { await clientEngine.AddStreamingAsync(magnetLink, saveDirectory, torrentSettings); } else { await clientEngine.AddAsync(magnetLink, saveDirectory, torrentSettings); } } } return(clientEngine); }
private BEncodedDictionary LoadFastResumeFile() { try { if (File.Exists(pathsManager.FastResumeFilePath)) { return(BEncodedValue.Decode <BEncodedDictionary>(File.ReadAllBytes(pathsManager.FastResumeFilePath))); } return(null); } catch { return(null); } }
internal Common.Torrent GetTorrent() { var calculatedInfoHash = SHA1Helper.ComputeHash(Stream.ToArray()); if (!Manager.InfoHash.Equals(calculatedInfoHash)) { throw new Exception("invalid metadata"); //restart ? } var d = BEncodedValue.Decode(Stream); var dict = new BEncodedDictionary { { "info", d } }; return(Common.Torrent.LoadCore(dict)); }
public async Task <TorrentManager> AddAsync(Torrent torrent, string saveDirectory, TorrentSettings settings) { await MainLoop.SwitchThread(); var metadata = new BEncodedDictionary { { "info", BEncodedValue.Decode(torrent.InfoMetadata) } }; var metadataCachePath = Settings.GetMetadataPath(torrent.InfoHash); Directory.CreateDirectory(Path.GetDirectoryName(metadataCachePath)); File.WriteAllBytes(metadataCachePath, metadata.Encode()); return(await AddAsync(null, torrent, saveDirectory, settings)); }
private void LoadFastResume(List <TorrentManager> managers) { BEncodedList list = (BEncodedList)BEncodedValue.Decode(File.ReadAllBytes(pathToFolderApplicationData + "\\FastResume.dat")); foreach (BEncodedDictionary fastResume in list) { FastResume data = new FastResume(fastResume); foreach (TorrentManager manager in managers) { if (manager.InfoHash == data.Infohash) { manager.LoadFastResume(data); } } } }
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 Torrent GetTorrent() { byte[] calculatedInfoHash; using (SHA1 sha = HashAlgoFactory.SHA1()) calculatedInfoHash = sha.ComputeHash(Stream.ToArray()); if (!Manager.InfoHash.Equals(calculatedInfoHash)) { throw new Exception("invalid metadata"); //restart ? } var d = BEncodedValue.Decode(Stream); var dict = new BEncodedDictionary { { "info", d } }; return(Torrent.LoadCore(dict)); }
public void benListDecoding() { byte[] data = Encoding.UTF8.GetBytes("l4:test5:tests6:testede"); using Stream stream = new MemoryStream(data); BEncodedValue result = BEncodedValue.Decode(stream); Assert.AreEqual(result.ToString(), "l4:test5:tests6:testede"); Assert.AreEqual(result is BEncodedList, true); BEncodedList list = (BEncodedList)result; Assert.AreEqual(list.Count, 3); Assert.AreEqual(list[0] is BEncodedString, true); Assert.AreEqual(((BEncodedString)list[0]).Text, "test"); Assert.AreEqual(((BEncodedString)list[1]).Text, "tests"); Assert.AreEqual(((BEncodedString)list[2]).Text, "tested"); }
public async Task SendAsync(byte[] buffer, IPEndPoint endpoint) { if (SendAsynchronously) { await Task.Yield(); } if (DhtMessageFactory.TryDecodeMessage(BEncodedValue.Decode <BEncodedDictionary> (buffer), out DhtMessage message)) { MessageSent?.Invoke(message, endpoint); } else { throw new Exception("Could not decode the message"); } }
private void ProcessMessage(byte[] buffer, IPEndPoint endpoint) { try { DhtMessage message; string error; if (MessageFactory.TryNoTraceDecodeMessage((BEncodedDictionary)BEncodedValue.Decode(buffer, 0, buffer.Length, false), out message, out error)) { if (message is QueryMessage) { message.Handle(this, new Node(message.Id, endpoint)); } } } catch { } }
public BEncodedSettingsStorage(string path) { this.path = path; this.settings = new BEncodedDictionary(); if (File.Exists(path)) { try { lock (this.flushLocker) using (BinaryReader reader = new BinaryReader(new FileStream(path, FileMode.Open))) this.settings = BEncodedValue.Decode(reader) as BEncodedDictionary; } catch (Exception) { } } }
public ClientEngine(EngineSettings settings, PeerListener listener, PieceWriter writer, string peerId = null) { Check.Settings(settings); Check.Listener(listener); Check.Writer(writer); this.listener = listener; this.settings = settings; if (settings.FastResumePath != null && File.Exists(settings.FastResumePath)) { var encodedListData = File.ReadAllBytes(settings.FastResumePath); var encodedList = (BEncodedList)BEncodedValue.Decode(encodedListData); _fastResume = encodedList.Cast <BEncodedDictionary>() .Select(x => new FastResume(x)); } connectionManager = new ConnectionManager(this); RegisterDht(new NullDhtEngine()); diskManager = new DiskManager(this, writer); listenManager = new ListenManager(this); MainLoop.QueueTimeout(TimeSpan.FromMilliseconds(TickLength), () => { if (IsRunning && !disposed) { LogicTick(); } return(!disposed); }); torrents = new List <TorrentManager>(); torrentsReadonly = new ReadOnlyCollection <TorrentManager>(torrents); CreateRateLimiters(); this.peerId = peerId ?? GeneratePeerId(); localPeerListener = new LocalPeerListener(this); localPeerManager = new LocalPeerManager(); LocalPeerSearchEnabled = SupportsLocalPeerDiscovery; listenManager.Register(listener); // This means we created the listener in the constructor if (listener.Endpoint.Port == 0) { listener.ChangeEndpoint(new IPEndPoint(IPAddress.Any, settings.ListenPort)); } }
private static async Task StartEngineV2() { EngineSettings engineSettings = new EngineSettings { SavePath = downloadsPath, ListenPort = 555 }; TorrentSettings torrentDefaults = new TorrentSettings(); engine = new ClientEngine(engineSettings); byte[] nodes = Array.Empty <byte>(); try { if (File.Exists(dhtNodeFile)) { nodes = File.ReadAllBytes(dhtNodeFile); } } catch { Console.WriteLine("No existing dht nodes could be loaded"); } DhtEngine dht = new DhtEngine(new IPEndPoint(IPAddress.Any, 555)); await engine.RegisterDhtAsync(dht); await engine.DhtEngine.StartAsync(nodes); fastResume = new BEncodedDictionary(); try { if (File.Exists(fastResumeFile)) { fastResume = BEncodedValue.Decode <BEncodedDictionary>(File.ReadAllBytes(fastResumeFile)); } } catch { } await engine.EnablePortForwardingAsync(CancellationToken.None); await engine.DisablePortForwardingAsync(CancellationToken.None); }
public void DownloadTorrent(int?torrentId) { using (var db = new OpenTrackerDbContext()) { var torrentExist = (from t in db.torrents where t.id == torrentId select t).Take(1).FirstOrDefault(); if (torrentExist == null) { Response.Write("Torrent not found."); return; } var file = string.Format("{0}.torrent", torrentExist.id); var finalTorrentPath = Path.Combine(TrackerSettings.TORRENT_DIRECTORY, file); var dictionary = (BEncodedDictionary)BEncodedValue.Decode(System.IO.File.ReadAllBytes(finalTorrentPath)); var userInformation = (from u in db.users where u.username == User.Identity.Name select u).Take(1).FirstOrDefault(); if (userInformation == null) { Response.Write("This shouldn't happen."); return; } var announceUrl = string.Format("{0}/announce/{1}", TrackerSettings.BASE_URL, userInformation.passkey); var editor = new TorrentEditor(dictionary) { Announce = announceUrl, Comment = "created by Open-Tracker.org" }; var privateTorrent = editor.ToDictionary().Encode(); var response = ControllerContext.HttpContext.Response; response.ClearHeaders(); response.AddHeader("Content-Disposition", string.Format("attachment; filename={0}-{1}.torrent", TrackerSettings.TORRENT_NAME_PREFIX, Url.Encode(torrentExist.torrentname))); response.AddHeader("Content-Type", "application/x-bittorrent"); response.BinaryWrite(privateTorrent); response.End(); } }
public void ErrorReceived() { int failedCount = 0; var pingSuccessful = new TaskCompletionSource <bool> (); var ping = new Ping(node.Id) { TransactionId = transactionId }; engine.MessageLoop.QuerySent += (o, e) => { // This ping should not time out. if (e.Query.TransactionId.Equals(ping.TransactionId)) { pingSuccessful.TrySetResult(!e.TimedOut && e.Response == null && e.Error != null); } }; listener.MessageSent += (data, endpoint) => { engine.MessageLoop.DhtMessageFactory.TryDecodeMessage(BEncodedValue.Decode <BEncodedDictionary> (data), out DhtMessage message); // This TransactionId should be registered and it should be pending a response. if (!DhtMessageFactory.IsRegistered(ping.TransactionId) || engine.MessageLoop.PendingQueries != 1) { pingSuccessful.TrySetResult(false); } if (message.TransactionId.Equals(ping.TransactionId)) { listener.RaiseMessageReceived(new ErrorMessage(ping.TransactionId, ErrorCode.ServerError, "Ooops"), node.EndPoint); failedCount++; } }; // Send the ping var task = engine.SendQueryAsync(ping, node); // The query should complete, and the message should not have timed out. Assert.IsTrue(task.Wait(100000), "#1"); Assert.IsTrue(pingSuccessful.Task.Wait(1000), "#2"); Assert.IsTrue(pingSuccessful.Task.Result, "#3"); Assert.IsFalse(DhtMessageFactory.IsRegistered(ping.TransactionId), "#4"); Assert.AreEqual(0, engine.MessageLoop.PendingQueries, "#5"); Assert.AreEqual(1, failedCount, "#6"); }
public void benDictionaryDecoding() { byte[] data = System.Text.Encoding.UTF8.GetBytes("d4:spaml1:a1:bee"); using (Stream stream = new MemoryStream(data)) { BEncodedValue result = BEncodedValue.Decode(stream); Assert.AreEqual(result.ToString(), "d4:spaml1:a1:bee"); Assert.AreEqual(result is BEncodedDictionary, true); BEncodedDictionary dict = (BEncodedDictionary)result; Assert.AreEqual(dict.Count, 1); Assert.IsTrue(dict["spam"] is BEncodedList); BEncodedList list = (BEncodedList)dict["spam"]; Assert.AreEqual(((BEncodedString)list[0]).Text, "a"); Assert.AreEqual(((BEncodedString)list[1]).Text, "b"); } }
async void MessageReceived(byte[] buffer, IPEndPoint endpoint) { await DhtEngine.MainLoop; // I should check the IP address matches as well as the transaction id // FIXME: This should throw an exception if the message doesn't exist, we need to handle this // and return an error message (if that's what the spec allows) try { if (DhtMessageFactory.TryDecodeMessage((BEncodedDictionary)BEncodedValue.Decode(buffer, 0, buffer.Length, false), out DhtMessage message)) { ReceiveQueue.Enqueue(new KeyValuePair <IPEndPoint, DhtMessage> (endpoint, message)); } } catch (MessageException) { // Caused by bad transaction id usually - ignore } catch (Exception) { //throw new Exception("IP:" + endpoint.Address.ToString() + "bad transaction:" + e.Message); } }
private static void Listener_MessageReceived(byte[] buffer, IPEndPoint endpoint) { try { Message message; string error; var data = (BEncodedDictionary)BEncodedValue.Decode(buffer, 0, buffer.Length, false); if (MessageFactory.TryDecodeMessage(data, out message, out error)) { logAdd(message.GetType().Name); Console.WriteLine("Get Msg {0}", message.GetType().Name); //if (message is GetPeers) // seeds.Add(((GetPeers)message).InfoHash); //else if (message is AnnouncePeer) { seeds.Add(((AnnouncePeer)message).InfoHash); } } else { logAdd(error); if (message != null) { logAdd("Bad " + message.GetType().Name); } else { logAdd("Null Msg"); } //Console.WriteLine(Convert.ToString(data)); } } catch (MonoTorrent.Dht.MessageException ex) { Console.WriteLine("Message Exception: {0}", ex); // Caused by bad transaction id usually - ignore } catch (Exception ex) { Console.WriteLine("OMGZERS! {0}", ex); //throw new Exception("IP:" + endpoint.Address.ToString() + "bad transaction:" + e.Message); } }