/// <summary> /// Reads the file list from a .torrent file. /// </summary> /// <param name="downloadPath"></param> /// <returns></returns> public static List<SimpleFileInfo> ReadTorrentFileList(string torrentFile) { if (!File.Exists(torrentFile)) throw new FileNotFoundException("Can't find file " + torrentFile); var ret = new List<SimpleFileInfo>(); //read and decode the .torrent file byte[] torrentBytes = File.ReadAllBytes(torrentFile); var torrentData = BEncodedValue.Decode<BEncodedDictionary>(torrentBytes); BEncodedList fileList = new BEncodedList(); try { fileList = torrentData.Item<BEncodedDictionary>("info").Item<BEncodedList>("files"); } catch { }; foreach (var fileItem in fileList) { var fileData = fileItem as BEncodedDictionary; string filePath = BuildPathFromDirectoryList(fileData.Item<BEncodedList>("path")); long length = fileData.Item<BEncodedNumber>("length").Number; ret.Add(new SimpleFileInfo(filePath, length)); } ret.Sort( new Comparison<SimpleFileInfo>( FileNameComparison)); return ret; }
public void CorruptDictionary() { var l = new BEncodedList(); var d = new BEncodedDictionary(); l.Add(d); IList<Peer> decoded = Peer.Decode(l); Assert.Equal(0, decoded.Count); }
public void CorruptDictionary() { BEncodedList l = new BEncodedList(); BEncodedDictionary d = new BEncodedDictionary(); l.Add(d); IList<Peer> decoded = Peer.Decode(l); Assert.AreEqual(0, decoded.Count, "#1"); }
public ErrorMessage(ErrorCode error, string message) : base(ErrorType) { var l = new BEncodedList(); l.Add(new BEncodedNumber((int) error)); l.Add(new BEncodedString(message)); properties.Add(ErrorListKey, l); }
public void CorruptDictionary() { var list = new BEncodedList(); var dictionary = new BEncodedDictionary(); list.Add(dictionary); IList<Peer> decoded = Peer.Decode(list); Assert.AreEqual(0, decoded.Count, "#1"); }
public void benDictionaryEncodingBuffered() { var data = Encoding.UTF8.GetBytes("d4:spaml1:a1:bee"); var dict = new BEncodedDictionary(); var list = new BEncodedList(); list.Add(new BEncodedString("a")); list.Add(new BEncodedString("b")); dict.Add("spam", list); var result = new byte[dict.LengthInBytes()]; dict.Encode(result, 0); Assert.True(Toolbox.ByteMatch(data, result)); }
public void benDictionaryEncoding() { var data = Encoding.UTF8.GetBytes("d4:spaml1:a1:bee"); var dict = new BEncodedDictionary(); var list = new BEncodedList(); list.Add(new BEncodedString("a")); list.Add(new BEncodedString("b")); dict.Add("spam", list); Assert.Equal(Encoding.UTF8.GetString(data), Encoding.UTF8.GetString(dict.Encode())); Assert.True(Toolbox.ByteMatch(data, dict.Encode())); }
public void benDictionaryEncoding() { byte[] data = System.Text.Encoding.UTF8.GetBytes("d4:spaml1:a1:bee"); BEncodedDictionary dict = new BEncodedDictionary(); BEncodedList list = new BEncodedList(); list.Add(new BEncodedString("a")); list.Add(new BEncodedString("b")); dict.Add("spam", list); Assert.AreEqual(System.Text.Encoding.UTF8.GetString(data), System.Text.Encoding.UTF8.GetString(dict.Encode())); Assert.IsTrue(Toolbox.ByteMatch(data, dict.Encode())); }
public void CorruptList() { var list = new BEncodedList(); for (var i = 0; i < peers.Count; i++) list.Add((BEncodedString) peers[i].CompactPeer()); list.Insert(2, new BEncodedNumber(5)); VerifyDecodedPeers(Peer.Decode(list)); list.Clear(); list.Add(new BEncodedString(new byte[3])); IList<Peer> decoded = Peer.Decode(list); Assert.Equal(0, decoded.Count); }
private void AddCommonStuff(BEncodedDictionary torrent) { if (Announces.Count > 0 && Announces[0].Count > 0) Announce = Announces[0][0]; if (GetrightHttpSeeds.Count > 0) { var seedlist = new BEncodedList(); seedlist.AddRange( GetrightHttpSeeds.ConvertAll<BEncodedValue>(delegate(string s) { return (BEncodedString) s; })); torrent["url-list"] = seedlist; } var span = DateTime.Now - new DateTime(1970, 1, 1); torrent["creation date"] = new BEncodedNumber((long) span.TotalSeconds); }
private static BEncodedDictionary CreateTorrent(int pieceLength) { var infoDict = new BEncodedDictionary(); infoDict[new BEncodedString("piece length")] = new BEncodedNumber(pieceLength); infoDict[new BEncodedString("pieces")] = new BEncodedString(new byte[20*15]); infoDict[new BEncodedString("length")] = new BEncodedNumber(15*256*1024 - 1); infoDict[new BEncodedString("name")] = new BEncodedString("test.files"); var dict = new BEncodedDictionary(); dict[new BEncodedString("info")] = infoDict; var announceTier = new BEncodedList(); announceTier.Add(new BEncodedString("custom://transfers1/announce")); announceTier.Add(new BEncodedString("custom://transfers2/announce")); announceTier.Add(new BEncodedString("http://transfers3/announce")); var announceList = new BEncodedList(); announceList.Add(announceTier); dict[new BEncodedString("announce-list")] = announceList; return dict; }
public override void Handle(DhtEngine engine, Node node) { base.Handle(engine, node); BEncodedString token = engine.TokenManager.GenerateToken(node); var response = new GetPeersResponse(engine.RoutingTable.LocalNode.Id, TransactionId, token); if (engine.Torrents.ContainsKey(InfoHash)) { var list = new BEncodedList(); foreach (Node n in engine.Torrents[InfoHash]) list.Add(n.CompactPort()); response.Values = list; } else { // Is this right? response.Nodes = Node.CompactNode(engine.RoutingTable.GetClosest(InfoHash)); } engine.MessageLoop.EnqueueSend(response, node.EndPoint); }
public static MonoTorrentCollection<Peer> Decode(BEncodedList peers) { var list = new MonoTorrentCollection<Peer>(peers.Count); foreach (var value in peers) { try { if (value is BEncodedDictionary) list.Add(DecodeFromDict((BEncodedDictionary) value)); else if (value is BEncodedString) foreach (var p in Decode((BEncodedString) value)) list.Add(p); } catch { // If something is invalid and throws an exception, ignore it // and continue decoding the rest of the peers } } return list; }
void AddCommonStuff(BEncodedDictionary torrent) { if (Announces.Count == 0 || (Announces.Count == 1 && Announces[0].Count <= 1)) { RemoveCustom("announce-list"); } if (Announces.Count > 0 && Announces[0].Count > 0) { Announce = Announces[0][0]; } if (GetrightHttpSeeds.Count > 0) { var seedlist = new BEncodedList(); seedlist.AddRange(GetrightHttpSeeds.Select(s => (BEncodedString)s)); torrent["url-list"] = seedlist; } TimeSpan span = DateTime.UtcNow - new DateTime(1970, 1, 1, 0, 0, 0, DateTimeKind.Utc); torrent["creation date"] = new BEncodedNumber((long)span.TotalSeconds); }
void Initialise(BEncodedDictionary metadata) { Metadata = metadata; BEncodedValue value; if (!Metadata.TryGetValue(AnnounceListKey, out value)) { value = new BEncodedList(); Metadata.Add(AnnounceListKey, value); } Announces = new RawTrackerTiers((BEncodedList)value); if (string.IsNullOrEmpty(Encoding)) { Encoding = "UTF-8"; } if (InfoDict == null) { InfoDict = new BEncodedDictionary(); } }
public override void Handle(DhtEngine engine, Node node) { base.Handle(engine, node); BEncodedString token = engine.TokenManager.GenerateToken(node); var response = new GetPeersResponse(engine.RoutingTable.LocalNode.Id, TransactionId, token); if (engine.Torrents.ContainsKey(InfoHash)) { var list = new BEncodedList(); foreach (Node n in engine.Torrents[InfoHash]) { list.Add(n.CompactPort()); } response.Values = list; } else { response.Nodes = Node.CompactNode(engine.RoutingTable.GetClosest(InfoHash)); } engine.MessageLoop.EnqueueSend(response, node, node.EndPoint); }
private static BEncodedDictionary CreateTorrent(int pieceLength) { BEncodedDictionary infoDict = new BEncodedDictionary(); infoDict[new BEncodedString("piece length")] = new BEncodedNumber(pieceLength); infoDict[new BEncodedString("pieces")] = new BEncodedString(new byte[20 * 15]); infoDict[new BEncodedString("length")] = new BEncodedNumber(15 * 256 * 1024 - 1); infoDict[new BEncodedString("name")] = new BEncodedString("test.files"); BEncodedDictionary dict = new BEncodedDictionary(); dict[new BEncodedString("info")] = infoDict; BEncodedList announceTier = new BEncodedList(); announceTier.Add(new BEncodedString("custom://transfers1/announce")); announceTier.Add(new BEncodedString("custom://transfers2/announce")); announceTier.Add(new BEncodedString("http://transfers3/announce")); BEncodedList announceList = new BEncodedList(); announceList.Add(announceTier); dict[new BEncodedString("announce-list")] = announceList; return(dict); }
void AddFiles(BEncodedDictionary dict, TorrentFile[] files) { long totalSize = piecelength - 1; BEncodedList bFiles = new BEncodedList(); for (int i = 0; i < files.Length; i++) { BEncodedList path = new BEncodedList(); foreach (string s in files[i].Path.Split('/')) { path.Add((BEncodedString)s); } BEncodedDictionary d = new BEncodedDictionary(); d["path"] = path; d["length"] = (BEncodedNumber)files[i].Length; bFiles.Add(d); totalSize += files[i].Length; } dict[new BEncodedString("files")] = bFiles; dict[new BEncodedString("name")] = new BEncodedString("test.files"); dict[new BEncodedString("piece length")] = new BEncodedNumber(piecelength); dict[new BEncodedString("pieces")] = new BEncodedString(new byte[20 * (totalSize / piecelength)]); }
///<summary> ///this method is used for multi file mode torrents to return a dictionary with ///file relevant informations. ///<param name="file">the file to report the informations for</param> ///<param name="basePath">used to subtract the absolut path information</param> ///</summary> BEncodedDictionary GetFileInfoDict(TorrentFile file) { var fileDict = new BEncodedDictionary(); fileDict.Add("length", new BEncodedNumber(file.Length)); var filePath = new BEncodedList(); var splittetPath = file.Path.Split(System.IO.Path.DirectorySeparatorChar); foreach (var s in splittetPath) { if (s.Length > 0) //exclude empties filePath.Add(new BEncodedString(s)); } fileDict.Add("path", filePath); return fileDict; }
/// <summary> /// Retrieves a semi-random list of peers which can be used to fulfill an Announce request /// </summary> /// <param name="response">The bencoded dictionary to add the peers to</param> /// <param name="count">The number of peers to add</param> /// <param name="compact">True if the peers should be in compact form</param> /// <param name="exlude">The peer to exclude from the list</param> internal void GetPeers(BEncodedDictionary response, int count, bool compact) { byte[] compactResponse = null; BEncodedList nonCompactResponse = null; int total = Math.Min(peers.Count, count); // If we have a compact response, we need to create a single BencodedString // Otherwise we need to create a bencoded list of dictionaries if (compact) compactResponse = new byte[total * 6]; else nonCompactResponse = new BEncodedList(total); int start = random.Next(0, peers.Count); lock (buffer) { if (buffer.Count != peers.Values.Count) buffer = new List<Peer>(peers.Values); } List<Peer> p = buffer; while (total > 0) { Peer current = p[(start++) % p.Count]; if (compact) { Buffer.BlockCopy(current.CompactEntry, 0, compactResponse, (total - 1) * 6, 6); } else { nonCompactResponse.Add(current.NonCompactEntry); } total--; } if (compact) response.Add(Tracker.PeersKey, (BEncodedString)compactResponse); else response.Add(Tracker.PeersKey, nonCompactResponse); }
public byte[] SaveNodes() { BEncodedList details = new BEncodedList(); MainLoop.QueueWait((MainLoopTask)delegate { foreach (Bucket b in RoutingTable.Buckets) { foreach (Node n in b.Nodes) if (n.State != NodeState.Bad) details.Add(n.CompactNode()); if (b.Replacement != null) if (b.Replacement.State != NodeState.Bad) details.Add(b.Replacement.CompactNode()); } }); return details.Encode(); }
public RawTrackerTier(BEncodedList tier) { Tier = tier; }
public void Add(BEncodedList nodes) { }
/// <summary> /// 将作为接入点被连接时候需要返回给对方的信息编码以供发送。 /// </summary> /// <returns>一个 B-编码形式的字节数组,包含了所需的信息。</returns> private byte[] EncodeTargetInformation(IPEndPoint targetEndPoint) { // 返回当前所有的连接信息 // 结构: // d // { // "connections" : l // { // d // { // "ip" : ip(4) // "port" : port(2) // } // } // "peers" : d // { // infohash_1 : l // { // d // { // "ip" : ip(4) // "port" : port(2) // } // } // ... infohash_n // } // "your endpoint" : d // { // "ip" : ip(4) // "port" : port(2) // } // } BEncodedDictionary dictionary = new BEncodedDictionary(); BEncodedList connList = new BEncodedList(ConnectionList.Count); lock (ConnectionList) { foreach (var item in ConnectionList) { var d = new BEncodedDictionary(); d.Add("ip", item.ClientLocation.GetAddressBytes()); d.Add("port", item.ClientLocation.GetPortBytes()); connList.Add(d); } } dictionary.Add("connections", connList); BEncodedDictionary peersList = new BEncodedDictionary(); lock (TrackerServer.Seeds) { foreach (var item in TrackerServer.Seeds) { var list = new BEncodedList(item.Value.Count); foreach (var t in item.Value) { var d = new BEncodedDictionary(); d.Add("ip", t.EndPoint.GetAddressBytes()); d.Add("port", t.EndPoint.GetPortBytes()); list.Add(d); } peersList.Add(item.Key.ToByteArray(), list); } } dictionary.Add("peers", peersList); BEncodedDictionary yourEndPoint = new BEncodedDictionary(); yourEndPoint.Add("ip", targetEndPoint.Address.GetAddressBytes()); yourEndPoint.Add("port", BitConverter.GetBytes((ushort)(targetEndPoint.Port & 0xffff))); dictionary.Add("your endpoint", yourEndPoint); byte[] data = dictionary.Encode(); return(data); }
public void benListEncodingBuffered() { byte[] data = System.Text.Encoding.UTF8.GetBytes("l4:test5:tests6:testede"); BEncodedList list = new BEncodedList(); list.Add(new BEncodedString("test")); list.Add(new BEncodedString("tests")); list.Add(new BEncodedString("tested")); byte[] result = new byte[list.LengthInBytes()]; list.Encode(result, 0); Assert.IsTrue(Toolbox.ByteMatch(data, result)); }
/// <summary> /// 解码连接到接入点时收到的字节数组,并应用这些信息。 /// </summary> /// <param name="data">收到的数据。</param> ///// <param name="sendPeerEnter">解码过程中是否应该广播 PeerEnterNetwork 消息。</param> /// <exception cref="System.FormatException">解码失败时发生。</exception> /// <remarks> /// 需要发送 PeerEnterNetwork 消息的情况会发生于:A开启客户端和μT,B开启客户端和μT,A(用户列表非空)再尝试连接B,此时如果B并没有保存全网的用户列表,那么A就要广播 PeerEnterNetwork。 /// </remarks> private void DecodeTargetInformation(byte[] data) { // 如果对方发过来的是空,那么就肯定不会有数据啦 if (data.Length > 0) { BEncodedDictionary dictionary = BEncodedDictionary.Decode(data) as BEncodedDictionary; if (dictionary == null) { throw new FormatException("无法解码。"); } BEncodedList connList = dictionary["connections"] as BEncodedList; BEncodedDictionary peersDict = dictionary["peers"] as BEncodedDictionary; // 规范 v1.2 // 先确认自己,同时 if ... 是兼容老版的通信 if (dictionary.ContainsKey("your endpoint")) { BEncodedDictionary yourEndPoint = dictionary["your endpoint"] as BEncodedDictionary; var ip = new IPAddress((yourEndPoint["ip"] as BEncodedString).TextBytes); var port = BitConverter.ToUInt16((yourEndPoint["port"] as BEncodedString).TextBytes, 0); // 分别设置 KClient、TrackerServer 和 BT 客户端的自己 SetLocalEndPoint(new IPEndPoint(ip, port)); TrackerServer.SetLocalEndPoint(new IPEndPoint(ip, TrackerServer.LocalEndPoint.Port)); TrackerServer.SetMyself(new IPEndPoint(ip, TrackerServer.Myself.EndPoint.GetPortNumber())); this.FreeToGo = true; TrackerServer.FreeToGo = true; } // ... lock (ConnectionList) { foreach (var item in connList) { var d = item as BEncodedDictionary; KEndPoint kep = KEndPoint.Empty; kep.SetAddress((d["ip"] as BEncodedString).TextBytes); kep.SetPort((int)BitConverter.ToUInt16((d["port"] as BEncodedString).TextBytes, 0)); try { AddToConnectionList(kep); } catch (Exception) { } } } // 如果已经有用户登记了,那么应该广播 if (TrackerServer.Seeds.Count > 0) { lock (TrackerServer.Seeds) { foreach (var kv in TrackerServer.Seeds) { // 广播消息 BroadcastMyselfAddAsPeer(kv.Key); } } } lock (TrackerServer.Seeds) { foreach (var kv in peersDict) { InfoHash infoHash = InfoHash.FromByteArray(kv.Key.TextBytes); List <Peer> peers = new List <Peer>((kv.Value as BEncodedList).Count); foreach (var item in (kv.Value as BEncodedList)) { var d = item as BEncodedDictionary; KEndPoint kep = KEndPoint.Empty; kep.SetAddress((d["ip"] as BEncodedString).TextBytes); kep.SetPort((int)BitConverter.ToUInt16((d["port"] as BEncodedString).TextBytes, 0)); Peer peer = Peer.Create(kep); peers.Add(peer); } try { TrackerServer.Seeds.Add(infoHash, peers); } catch (Exception) { } } } } else { Logger.Log("待解码的数据为空,这意味着对方客户端目前持有的连接列表和用户列表为空。"); } }
private void AddFiles(BEncodedDictionary dict, TorrentFile[] files) { long totalSize = piecelength - 1; var bFiles = new BEncodedList(); for (var i = 0; i < files.Length; i++) { var path = new BEncodedList(); foreach (var s in files[i].Path.Split('/')) path.Add((BEncodedString) s); var d = new BEncodedDictionary(); d["path"] = path; d["length"] = (BEncodedNumber) files[i].Length; bFiles.Add(d); totalSize += files[i].Length; } dict[new BEncodedString("files")] = bFiles; dict[new BEncodedString("name")] = new BEncodedString("test.files"); dict[new BEncodedString("piece length")] = new BEncodedNumber(piecelength); dict[new BEncodedString("pieces")] = new BEncodedString(new byte[20*(totalSize/piecelength)]); }
public void benListEncoding() { byte[] data = System.Text.Encoding.UTF8.GetBytes("l4:test5:tests6:testede"); BEncodedList list = new BEncodedList(); list.Add(new BEncodedString("test")); list.Add(new BEncodedString("tests")); list.Add(new BEncodedString("tested")); Assert.IsTrue(Toolbox.ByteMatch(data, list.Encode())); }
private static void AddAnnounces(BEncodedDictionary dict, string[][] tiers) { var announces = new BEncodedList(); foreach (var tier in tiers) { var bTier = new BEncodedList(); announces.Add(bTier); foreach (var s in tier) bTier.Add((BEncodedString) s); } dict["announce"] = (BEncodedString) tiers[0][0]; dict["announce-list"] = announces; }
protected override void HandleLtMetadataMessage(PeerId id, LTMetadata message) { base.HandleLtMetadataMessage(id, message); switch (message.MetadataMessageType) { case LTMetadata.eMessageType.Data: if (Stream == null) { throw new Exception("Need extention handshake before ut_metadata message."); } Stream.Seek(message.Piece * LTMetadata.BlockSize, SeekOrigin.Begin); Stream.Write(message.MetadataPiece, 0, message.MetadataPiece.Length); bitField[message.Piece] = true; if (bitField.AllTrue) { byte[] hash; Stream.Position = 0; using (SHA1 hasher = HashAlgoFactory.Create <SHA1> ()) hash = hasher.ComputeHash(Stream); if (!Manager.InfoHash.Equals(hash)) { bitField.SetAll(false); } else { Stream.Position = 0; BEncodedDictionary dict = new BEncodedDictionary(); dict.Add("info", BEncodedValue.Decode(Stream)); if (Manager.TrackerManager.Tiers != null && Manager.TrackerManager.Tiers.Count > 0) { BEncodedList announceTrackers = new BEncodedList(); foreach (var tier in Manager.TrackerManager.Tiers) { BEncodedList announceUrls = new BEncodedList(); foreach (var tracker in tier.Trackers) { announceUrls.Add(new BEncodedString(tracker.Uri.OriginalString)); } announceTrackers.Add(announceUrls); } dict.Add("announce-list", announceTrackers); } if (Torrent.TryLoad(dict.Encode(), out Torrent t)) { Manager.RaiseMetadataReceived(t, dict); if (stopWhenDone) { return; } try { if (Directory.Exists(savePath)) { savePath = Path.Combine(savePath, $"{Manager.InfoHash.ToHex ()}.torrent"); } File.Delete(savePath); File.WriteAllBytes(savePath, dict.Encode()); } catch (Exception ex) { Logger.Log(null, "*METADATA EXCEPTION* - Can not write in {0} : {1}", savePath, ex); Manager.TrySetError(Reason.WriteFailure, ex); return; } t.TorrentPath = savePath; Manager.Torrent = t; SwitchToRegular(); } else { bitField.SetAll(false); } } } //Double test because we can change the bitfield in the other block if (!bitField.AllTrue) { RequestNextNeededPiece(id); } break; case LTMetadata.eMessageType.Reject: //TODO //Think to what we do in this situation //for moment nothing ;) //reject or flood? break; case LTMetadata.eMessageType.Request: //ever done in base class but needed to avoid default break; default: throw new MessageException($"Invalid messagetype in LTMetadata: {message.MetadataMessageType}"); } }
/// <summary> /// 处理 Tracker 请求的方法。 /// </summary> /// <param name="processor">为此请求生成的 <see cref="Kei.KTracker.HttpProcessor"/> 对象。</param> /// <param name="ioStream"><see cref="Kei.KTracker.HttpProcessor"/> 为此请求开启的 <see cref="System.IO.Stream"/>。</param> /// <param name="parameters">URL 请求参数。</param> private void HandleTrackerRequest(HttpProcessor processor, Stream ioStream, string parameters) { // parameters 传入类似 info_hash=XXXX&port=XXXX&ipv6=XXXX 的形式 var args = Utilities.DecomposeParameterString(parameters); Logger.Log("[Tracker]请求: " + processor.RequestUrl); try { Logger.Log("[Tracker]解码收到的参数。"); // 先解码处理各种参数(注意可能会引发异常) string infoHashString = Utilities.UnescapePartialUriEncodedString(args["info_hash"]); InfoHash infoHash = InfoHash.FromHexString(infoHashString); int portNo = Convert.ToInt32(args["port"]); TaskStatus taskStatus; if (args.ContainsKey("event")) { switch (args["event"]) { case "started": taskStatus = TaskStatus.Started; break; case "stopped": taskStatus = TaskStatus.Stopped; break; case "paused": taskStatus = TaskStatus.Paused; break; default: taskStatus = TaskStatus.None; break; } } else { taskStatus = TaskStatus.None; } bool compact; if (args.ContainsKey("compact")) { var n = Convert.ToInt32(args["compact"]); compact = n != 0; } else { compact = false; } bool noPeerID; if (args.ContainsKey("no_peer_id")) { var n = Convert.ToInt32(args["no_peer_id"]); noPeerID = n != 0; } else { noPeerID = false; } var peerIDString = Utilities.UnescapePartialUriEncodedString(args["peer_id"]); // 别忘了重新确认自己 IPEndPoint newMyself = new IPEndPoint(LocalEndPoint.Address, portNo); Logger.Log("[Tracker]新的自己(BitTorrent 客户端): " + newMyself.ToString()); SetMyself(newMyself, peerIDString); List <Peer> peers = null; TrackerCommEventArgs eventArgs; // 如果接入分布网络完成 if (FreeToGo) { // 触发事件,得到新的可用用户列表 if (Seeds.TryGetValue(infoHash, out peers)) { peers = Seeds[infoHash]; if (peers.IndexOf(_myself) < 0) { // 如果之前我不在种子列表中 // TODO: 添加 myself peers.Add(_myself); // 而且此时确认为自己加入网络,强制设定 event=started taskStatus = TaskStatus.Started; } } else { // 如果之前没有相关种子 peers = new List <Peer>(); // TODO: 添加 myself peers.Add(_myself); Seeds.Add(infoHash, peers); // 而且此时确认为自己加入网络,强制设定 event=started taskStatus = TaskStatus.Started; } } eventArgs = new TrackerCommEventArgs(infoHash, peers, portNo, peerIDString, compact, noPeerID, taskStatus); EventHelper.RaiseEventAsync(TrackerComm, this, eventArgs); //if (eventArgs.Peers == null) //{ // throw new NullReferenceException("Peers list is null"); //} if (eventArgs.Peers != null) { peers = eventArgs.Peers; } // 生成返回给 μTorrent 的信息 Logger.Log("[Tracker]反馈给 BitTorrent 客户端。"); if (peers != null) { string peersListString = "[Tracker]种子 " + infoHash.ToString() + " 的用户列表如下:"; foreach (var p in peers) { peersListString += Environment.NewLine + p.EndPoint.ToString(); } Logger.Log(peersListString); } else { Logger.Log("[Tracker]种子 " + infoHash.ToString() + " 的用户列表为空。"); } BEncodedDictionary data = new BEncodedDictionary(); data.Add("interval", 60); if (peers != null) { // 如果种子列表里有种子 // 为了防止其他线程修改这个 list 导致迭代器失效,先锁定这个对象 lock (peers) { if (compact) { // 生成字节数组 byte[] peersArray = new byte[peers.Count * 6]; byte[] tmp; int i = 0; foreach (var peer in peers) { tmp = peer.ToByteArray(); Array.Copy(tmp, 0, peersArray, i * 6, 6); i++; } data.Add("peers", peersArray); } else { // 生成列表 BEncodedList peersList = new BEncodedList(peers.Count); foreach (var peer in peers) { BEncodedDictionary peerDict = new BEncodedDictionary(); peerDict.Add("id", peer.ID); peerDict.Add("ip", peer.EndPoint.GetAddressString()); peerDict.Add("port", peer.EndPoint.GetPortNumber()); peersList.Add(peerDict); } data.Add("peers", peersList); } } data.Add("complete", peers.Count); } else { // 如果没有种子,就返回空列表 data.Add("peers", string.Empty); } // 输出 Logger.Log("[Tracker]写入“成功”头。"); processor.WriteSuccess(null, "text/plain"); Logger.Log("[Tracker]编码返回数据。"); var dataBytes = data.Encode(); Logger.Log("[Tracker]写入返回数据。"); ioStream.Write(dataBytes, 0, dataBytes.Length); Logger.Log("[Tracker]向 BitTorrent 客户端返回了: " + Encoding.ASCII.GetString(dataBytes)); ioStream.Flush(); } catch (Exception ex) { Logger.Log(ex.Message + Environment.NewLine + ex.StackTrace); processor.WriteFailure(); ioStream.WriteLine(ex.Message); ioStream.WriteLine(ex.StackTrace); } }
/// <summary> /// This method is called internally to load in all the files found within the "Files" section /// of the .torrents infohash /// </summary> /// <param name="list">The list containing the files available to download</param> private void LoadTorrentFiles(BEncodedList list) { List <TorrentFile> files = new List <TorrentFile>(); int endIndex; long length; string path; byte[] md5sum; byte[] ed2k; byte[] sha1; int startIndex; StringBuilder sb = new StringBuilder(32); foreach (BEncodedDictionary dict in list) { length = 0; path = null; md5sum = null; ed2k = null; sha1 = null; foreach (KeyValuePair <BEncodedString, BEncodedValue> keypair in dict) { switch (keypair.Key.Text) { case ("sha1"): sha1 = ((BEncodedString)keypair.Value).TextBytes; break; case ("ed2k"): ed2k = ((BEncodedString)keypair.Value).TextBytes; break; case ("length"): length = long.Parse(keypair.Value.ToString()); break; case ("path.utf-8"): foreach (BEncodedString str in ((BEncodedList)keypair.Value)) { sb.Append(str.Text); sb.Append(Path.DirectorySeparatorChar); } path = sb.ToString(0, sb.Length - 1); sb.Remove(0, sb.Length); break; case ("path"): if (string.IsNullOrEmpty(path)) { foreach (BEncodedString str in ((BEncodedList)keypair.Value)) { sb.Append(str.Text); sb.Append(Path.DirectorySeparatorChar); } path = sb.ToString(0, sb.Length - 1); sb.Remove(0, sb.Length); } break; case ("md5sum"): md5sum = ((BEncodedString)keypair.Value).TextBytes; break; default: break; //FIXME: Log unknown values } } // A zero length file always belongs to the same piece as the previous file if (length == 0) { if (files.Count > 0) { startIndex = files[files.Count - 1].EndPieceIndex; endIndex = files[files.Count - 1].EndPieceIndex; } else { startIndex = 0; endIndex = 0; } } else { startIndex = (int)(size / pieceLength); endIndex = (int)((size + length) / pieceLength); if ((size + length) % pieceLength == 0) { endIndex--; } } files.Add(new TorrentFile(path, length, path, startIndex, endIndex, (int)(size % pieceLength), md5sum, ed2k, sha1)); size += length; } this.torrentFiles = files.ToArray(); }
/// <summary> /// Construis l'instance /// </summary> private void LoadTorrent() { if (_data == null) { throw new ArgumentNullException("_data", "_data cannot be null."); } //on récupère chacune des données si présentes if (_data.ContainsKey("creation date")) { CreationDate = _data["creation date"]; } if (_data.ContainsKey("created by")) { CreatedBy = _data["created by"]; } if (_data.ContainsKey("comment")) { Comment = _data["comment"]; } if (_data.ContainsKey("announce")) { Tracker tracker = new Tracker(_data["announce"]); Trackers.Add(new TorrentTracker(this, tracker)); } if (_data.ContainsKey("info")) { BEncodedDictionary info = (BEncodedDictionary)_data["info"]; if (info.ContainsKey("piece length")) { PieceLength = info["piece length"]; } if (info.ContainsKey("pieces")) { Pieces = info["pieces"]; } if (info.ContainsKey("name")) { Name = info["name"]; } //on véfifie la présence des fichiers if (info.ContainsKey("files")) { BEncodedList files = (BEncodedList)info["files"]; foreach (var item in files) { BEncodedDictionary fileEncoded = (BEncodedDictionary)item; File file = new File(fileEncoded["path"], fileEncoded["length"]); Files.Add(file); } } } }
IList <TorrentFile> LoadTorrentFiles(BEncodedList list) { var sb = new StringBuilder(32); var files = new List <(string path, long length, byte[] md5sum, byte[] ed2k, byte[] sha1)> (); foreach (BEncodedDictionary dict in list) { long length = 0; string path = null; byte[] md5sum = null; byte[] ed2k = null; byte[] sha1 = null; foreach (KeyValuePair <BEncodedString, BEncodedValue> keypair in dict) { switch (keypair.Key.Text) { case ("sha1"): sha1 = ((BEncodedString)keypair.Value).TextBytes; break; case ("ed2k"): ed2k = ((BEncodedString)keypair.Value).TextBytes; break; case ("length"): length = long.Parse(keypair.Value.ToString()); break; case ("path.utf-8"): foreach (BEncodedString str in ((BEncodedList)keypair.Value)) { sb.Append(str.Text); sb.Append(Path.DirectorySeparatorChar); } path = sb.ToString(0, sb.Length - 1); sb.Remove(0, sb.Length); break; case ("path"): if (string.IsNullOrEmpty(path)) { foreach (BEncodedString str in ((BEncodedList)keypair.Value)) { sb.Append(str.Text); sb.Append(Path.DirectorySeparatorChar); } path = sb.ToString(0, sb.Length - 1); sb.Remove(0, sb.Length); } break; case ("md5sum"): md5sum = ((BEncodedString)keypair.Value).TextBytes; break; default: break; //FIXME: Log unknown values } } PathValidator.Validate(path); files.Add((path, length, md5sum, ed2k, sha1)); Size += length; } return(Array.AsReadOnly(TorrentFile.Create(PieceLength, files.ToArray()))); }
public void SaveFastResume() { if (string.IsNullOrWhiteSpace(settings.FastResumePath)) return; var encodedList = new BEncodedList(); var fastResumeData = torrentsReadonly .Where(x => x.HashChecked) .Select(tm => tm.SaveFastResume().Encode()); foreach (var data in fastResumeData) encodedList.Add(data); File.WriteAllBytes(settings.FastResumePath, encodedList.Encode()); }
public void GetPeersResponseDecode() { GetPeersEncode(); MessageFactory.RegisterSend(message); string text = "d1:rd2:id20:abcdefghij01234567895:token8:aoeusnth6:valuesl6:axje.u6:idhtnmee1:t2:aa1:y1:re"; GetPeersResponse m = (GetPeersResponse)Decode(text); Assert.AreEqual(token, m.Token, "#1"); Assert.AreEqual(id, m.Id, "#2"); BEncodedList l = new BEncodedList(); l.Add((BEncodedString)"axje.u"); l.Add((BEncodedString)"idhtnm"); Assert.AreEqual(l, m.Values, "#3"); Compare(m, text); }
/// <summary> /// Builds an complete path from a list of directories. /// </summary> /// <param name="pathParts"></param> /// <returns></returns> private static string BuildPathFromDirectoryList(BEncodedList pathParts) { string ret = string.Empty; foreach (var p in pathParts) ret = Path.Combine(ret, (p as BEncodedString).Text); return ret; }
private BEncodedValue ToFileInfoDict(TorrentFile file) { var fileDict = new BEncodedDictionary(); var filePath = new BEncodedList(); var splittetPath = file.Path.Split(new[] {Path.DirectorySeparatorChar}, StringSplitOptions.RemoveEmptyEntries); foreach (var s in splittetPath) filePath.Add(new BEncodedString(s)); fileDict["length"] = new BEncodedNumber(file.Length); fileDict["path"] = filePath; if (file.MD5 != null) fileDict["md5sum"] = (BEncodedString) file.MD5; return fileDict; }
public RawTrackerTiers(BEncodedList tiers) { Tiers = tiers; }
public void Add(BEncodedList nodes) { // Maybe we should pipeline all our tasks to ensure we don't flood the DHT engine. // I don't think it's *bad* that we can run several initialise tasks simultaenously // but it might be better to run them sequentially instead. We should also // run GetPeers and Announce tasks sequentially. InitialiseTask task = new InitialiseTask(this, Node.FromCompactNode (nodes)); task.Execute(); }
///<summary> ///this adds stuff common to single and multi file torrents ///</summary> void AddCommonStuff(BEncodedDictionary torrent) { if (announces.Count > 0 && announces[0].Count > 0) torrent.Add("announce", new BEncodedString(announces[0][0])); // If there is more than one tier or the first tier has more than 1 tracker if (announces.Count > 1 || (announces.Count > 0 && announces[0].Count > 1)) { var announceList = new BEncodedList(); for (var i = 0; i < announces.Count; i++) { var tier = new BEncodedList(); for (var j = 0; j < announces[i].Count; j++) tier.Add(new BEncodedString(announces[i][j])); announceList.Add(tier); } torrent.Add("announce-list", announceList); } var epocheStart = new DateTime(1970, 1, 1); var span = DateTime.Now - epocheStart; Logger.Log(null, "creation date: {0} - {1} = {2}:{3}", DateTime.Now, epocheStart, span, span.TotalSeconds); torrent.Add("creation date", new BEncodedNumber((long)span.TotalSeconds)); }
protected override void HandleLtMetadataMessage(PeerId id, LTMetadata message) { base.HandleLtMetadataMessage(id, message); switch (message.MetadataMessageType) { case LTMetadata.eMessageType.Data: // If we've already received everything successfully, do nothing! if (bitField.AllTrue) { return; } if (Stream == null) { throw new Exception("Need extention handshake before ut_metadata message."); } Stream.Seek(message.Piece * LTMetadata.BlockSize, SeekOrigin.Begin); Stream.Write(message.MetadataPiece, 0, message.MetadataPiece.Length); bitField[message.Piece] = true; if (bitField.AllTrue) { byte[] hash; Stream.Position = 0; using (SHA1 hasher = HashAlgoFactory.SHA1()) hash = hasher.ComputeHash(Stream); if (!Manager.InfoHash.Equals(hash)) { bitField.SetAll(false); } else { Stream.Position = 0; BEncodedDictionary dict = new BEncodedDictionary(); dict.Add("info", BEncodedValue.Decode(Stream)); if (Manager.TrackerManager.Tiers != null && Manager.TrackerManager.Tiers.Count > 0) { BEncodedList announceTrackers = new BEncodedList(); foreach (var tier in Manager.TrackerManager.Tiers) { BEncodedList announceUrls = new BEncodedList(); foreach (var tracker in tier.Trackers) { announceUrls.Add(new BEncodedString(tracker.Uri.OriginalString)); } announceTrackers.Add(announceUrls); } dict.Add("announce-list", announceTrackers); } var rawData = dict.Encode(); if (Torrent.TryLoad(rawData, out Torrent t)) { if (stopWhenDone) { Manager.RaiseMetadataReceived(rawData); return; } try { if (this.Settings.AutoSaveLoadMagnetLinkMetadata) { if (!Directory.Exists(Path.GetDirectoryName(savePath))) { Directory.CreateDirectory(Path.GetDirectoryName(savePath)); } File.Delete(savePath); File.WriteAllBytes(savePath, dict.Encode()); } } catch (Exception ex) { logger.ExceptionFormated(ex, "Cannot write metadata to path '{0}'", savePath); Manager.TrySetError(Reason.WriteFailure, ex); return; } Manager.SetMetadata(t); _ = Manager.StartAsync(); Manager.RaiseMetadataReceived(rawData); } else { bitField.SetAll(false); } } } RequestNextNeededPiece(id); break; case LTMetadata.eMessageType.Reject: //TODO //Think to what we do in this situation //for moment nothing ;) //reject or flood? break; case LTMetadata.eMessageType.Request: //ever done in base class but needed to avoid default break; default: throw new MessageException($"Invalid messagetype in LTMetadata: {message.MetadataMessageType}"); } }
private void ProcessTorrentGen(string sContentUniqueId, ContentGenRecipes oRecipes, EventHandler <TorrentCreatorEventArgs> callbackHashed, out string sContentHashCode) { long lPieceLengthKB = AppConfig.ContentGenJob.PieceLengthKB; string sCreatedBy = AppConfig.ContentGenJob.CreatedBy; string sTrackerAnnounceUrl = AppConfig.ContentGenJob.TrackerAnnounceUrl; string sInternalTrackerAnnounceUrl = AppConfig.ContentGenJob.InternalTrackerAnnounceUrl; // Initialization _InterruptFlag = false; sContentHashCode = ""; // Initialize the torrent creation task MetafileGenTask oMG = new MetafileGenTask(); oMG.Hashed += callbackHashed; // Set the torrent info oMG.PieceLength = lPieceLengthKB * 1024; // Torrent info: PieceLength oMG.StoreMD5 = false; // Don't store MD5SUM in the torrent file oMG.Private = true; // Always be private torrent oMG.CreatedBy = sCreatedBy; // Torrent info: CreatedBy if (oRecipes.HttpSeedsUrl != null && oRecipes.HttpSeedsUrl.Length > 0) { List <string> listUrls = oRecipes.HttpSeedsUrlList; listUrls.ForEach(sUrl => { oMG.GetrightHttpSeeds.Add(sUrl); }); // URL seed } List <string> oAnn = new List <string>(); oAnn.Add(sTrackerAnnounceUrl); oMG.Announces.Add(oAnn); // Torrent Info: Tracker Server // Assign the custom fields to the "info" section of the torrent oMG.AddCustomSecure("ga account name", new BEncodedString(oRecipes.GAProfileId)); oMG.AddCustomSecure("ga host name", new BEncodedString("http://www.gamania.com")); oMG.AddCustomSecure("custom display name", new BEncodedString(oRecipes.DownloaderDisplayName)); // Begin the async torrent creation process IAsyncResult asyncResult = oMG.BeginCreate( oRecipes.ContentSourceUrl, // Content Source URL null, // No callback needed oRecipes.ContentSourceUrl // Async state ); // Wait for the completion or the aborting if (!asyncResult.IsCompleted) { while (!asyncResult.AsyncWaitHandle.WaitOne(1000)) { if (_InterruptFlag) { oMG.AbortCreation(); // Try to abort the task } } } // End of the async torre creation BEncodedDictionary oTorrentBenDict = oMG.EndCreate(asyncResult); // Get the content hash code from the torrent file sContentHashCode = Torrent.Load(oTorrentBenDict).InfoHash.ToHex(); lock (sigLock) { // ========= Save 3 types of torrent files for 3 different usages ============== // 1. Save the torrent file which contains the public tracker announce URL File.WriteAllBytes( ContentWorkingPath + "\\" + sContentUniqueId + "\\" + sContentHashCode + TorrentExtension, oTorrentBenDict.Encode()); // 2. Save the VIP torrent file contains the public tracker announce URL if (oRecipes.VipHttpSeedsUrl != null && oRecipes.VipHttpSeedsUrl.Length > 0) { // Add more Url Seed Urls List <string> listUrls = oRecipes.VipHttpSeedsUrlList; listUrls.ForEach(sUrl => { oMG.GetrightHttpSeeds.Add(sUrl); }); // Add more URL seed // Convert to Ben-Encoded List BEncodedList listUrlSeeds = new BEncodedList(); listUrlSeeds.AddRange(oMG.GetrightHttpSeeds.ConvertAll <BEncodedValue>(s => { return((BEncodedString)s); })); oTorrentBenDict[TorrentInfoUrlListKey] = listUrlSeeds; } // Save the VIP Torrent file File.WriteAllBytes( ContentWorkingPath + "\\" + sContentUniqueId + "\\" + sContentHashCode + TorrentVipExtension, oTorrentBenDict.Encode()); // 3. Save the FQDN torrent file which contains the internal tracker announce URL // First, add the content source URL to the torrent to accelerate the download speed if (-1 == oRecipes.HttpSeedsUrlList.FindIndex(x => { return(x.Equals(oRecipes.ContentSourceUrl)); }) && -1 == oRecipes.VipHttpSeedsUrlList.FindIndex(x => { return(x.Equals(oRecipes.ContentSourceUrl)); })) { // Add the content source URL to the TorrentInfoUrlListKey // together with the VIP URL seeds just added previously oMG.GetrightHttpSeeds.Add(oRecipes.ContentSourceUrl); // Convert to Ben-Encoded List BEncodedList listUrlSeeds = new BEncodedList(); listUrlSeeds.AddRange(oMG.GetrightHttpSeeds.ConvertAll <BEncodedValue>(s => { return((BEncodedString)s); })); oTorrentBenDict[TorrentInfoUrlListKey] = listUrlSeeds; } // Second, replace the tracker announce URL with the internal tracker announce URL oTorrentBenDict[TorrentInfoAnnounceKey] = new BEncodedString(sInternalTrackerAnnounceUrl); // Save the FQDN Torrent file File.WriteAllBytes( ContentWorkingPath + "\\" + sContentUniqueId + "\\" + sContentHashCode + TorrentFqdnExtension, oTorrentBenDict.Encode()); } }
internal static IList <Peer> Decode(BEncodedList l) => PeerDecoder.Decode(l).Select(t => new Peer(BEncodedString.FromMemory(t.PeerId), t.Uri)).ToArray();
private BEncodedList CreateFiles() { var files = new BEncodedList(); var path = new BEncodedList { new BEncodedString("file1.txt") }; var file = new BEncodedDictionary { { "sha1", new BEncodedString(_sha.ComputeHash(System.Text.Encoding.UTF8.GetBytes("file1 hash1"))) }, { "ed2k", new BEncodedString(_sha.ComputeHash(System.Text.Encoding.UTF8.GetBytes("file1 hash2"))) }, { "length", new BEncodedNumber(50000) }, { "md5sum", new BEncodedString(_sha.ComputeHash(System.Text.Encoding.UTF8.GetBytes("file1 hash3"))) }, { "path.utf-8", path }, { "path", path } }; files.Add(file); path = new BEncodedList { new BEncodedString("subfolder1"), new BEncodedString("file2.txt") }; file = new BEncodedDictionary { { "sha1", new BEncodedString(_sha.ComputeHash(System.Text.Encoding.UTF8.GetBytes("file1 hash1"))) }, { "ed2k", new BEncodedString(_sha.ComputeHash(System.Text.Encoding.UTF8.GetBytes("file1 hash2"))) }, { "length", new BEncodedNumber(60000) }, { "md5sum", new BEncodedString(_sha.ComputeHash(System.Text.Encoding.UTF8.GetBytes("file1 hash3"))) }, { "path.utf-8", path }, { "path", path } }; files.Add(file); path = new BEncodedList { new BEncodedString("subfolder1"), new BEncodedString("subfolder2"), new BEncodedString("file3.txt") }; file = new BEncodedDictionary { { "sha1", new BEncodedString(_sha.ComputeHash(System.Text.Encoding.UTF8.GetBytes("file1 hash1"))) }, { "ed2k", new BEncodedString(_sha.ComputeHash(System.Text.Encoding.UTF8.GetBytes("file1 hash2"))) }, { "length", new BEncodedNumber(70000) }, { "md5sum", new BEncodedString(_sha.ComputeHash(System.Text.Encoding.UTF8.GetBytes("file1 hash3"))) }, { "path.utf-8", path }, { "path", path } }; files.Add(file); path = new BEncodedList { new BEncodedString("subfolder1"), new BEncodedString("subfolder2"), new BEncodedString("file4.txt") }; file = new BEncodedDictionary { { "sha1", new BEncodedString(_sha.ComputeHash(System.Text.Encoding.UTF8.GetBytes("file1 hash1"))) }, { "ed2k", new BEncodedString(_sha.ComputeHash(System.Text.Encoding.UTF8.GetBytes("file1 hash2"))) }, { "length", new BEncodedNumber(80000) }, { "md5sum", new BEncodedString(_sha.ComputeHash(System.Text.Encoding.UTF8.GetBytes("file1 hash3"))) }, { "path.utf-8", path }, { "path", path } }; files.Add(file); return(files); }
///<summary> ///used for creating multi file mode torrents. ///</summary> ///<returns>the dictionary representing which is stored in the torrent file</returns> protected void CreateMultiFileTorrent(BEncodedDictionary dictionary, TorrentFile[] files, PieceWriter writer, string name) { AddCommonStuff(dictionary); var info = (BEncodedDictionary)dictionary["info"]; var torrentFiles = new BEncodedList(); //the dict which hold the file infos for (var i = 0; i < files.Length; i++) torrentFiles.Add(GetFileInfoDict(files[i])); info.Add("files", torrentFiles); Logger.Log(null, "Topmost directory: {0}", name); info.Add("name", new BEncodedString(name)); info.Add("pieces", new BEncodedString(CalcPiecesHash(Path, files, writer))); }
public void DecodeDictionary() { var list = new BEncodedList(); foreach (var p in peers) { var dict = new BEncodedDictionary(); dict.Add("ip", (BEncodedString) p.ConnectionUri.Host); dict.Add("port", (BEncodedNumber) p.ConnectionUri.Port); dict.Add("peer id", (BEncodedString) p.PeerId); list.Add(dict); } VerifyDecodedPeers(Peer.Decode(list)); }
private BEncodedList CreateFiles() { BEncodedList files = new BEncodedList(); BEncodedDictionary file; BEncodedList path; path = new BEncodedList(); path.Add(new BEncodedString("file1.txt")); file = new BEncodedDictionary(); file.Add("sha1", new BEncodedString(sha.ComputeHash(System.Text.Encoding.UTF8.GetBytes("file1 hash1")))); file.Add("ed2k", new BEncodedString(sha.ComputeHash(System.Text.Encoding.UTF8.GetBytes("file1 hash2")))); file.Add("length", new BEncodedNumber(50000)); file.Add("md5sum", new BEncodedString(sha.ComputeHash(System.Text.Encoding.UTF8.GetBytes("file1 hash3")))); file.Add("path.utf-8", path); file.Add("path", path); files.Add(file); path = new BEncodedList(); path.Add(new BEncodedString("subfolder1")); path.Add(new BEncodedString("file2.txt")); file = new BEncodedDictionary(); file.Add("sha1", new BEncodedString(sha.ComputeHash(System.Text.Encoding.UTF8.GetBytes("file1 hash1")))); file.Add("ed2k", new BEncodedString(sha.ComputeHash(System.Text.Encoding.UTF8.GetBytes("file1 hash2")))); file.Add("length", new BEncodedNumber(60000)); file.Add("md5sum", new BEncodedString(sha.ComputeHash(System.Text.Encoding.UTF8.GetBytes("file1 hash3")))); file.Add("path.utf-8", path); file.Add("path", path); files.Add(file); path = new BEncodedList(); path.Add(new BEncodedString("subfolder1")); path.Add(new BEncodedString("subfolder2")); path.Add(new BEncodedString("file3.txt")); file = new BEncodedDictionary(); file.Add("sha1", new BEncodedString(sha.ComputeHash(System.Text.Encoding.UTF8.GetBytes("file1 hash1")))); file.Add("ed2k", new BEncodedString(sha.ComputeHash(System.Text.Encoding.UTF8.GetBytes("file1 hash2")))); file.Add("length", new BEncodedNumber(70000)); file.Add("md5sum", new BEncodedString(sha.ComputeHash(System.Text.Encoding.UTF8.GetBytes("file1 hash3")))); file.Add("path.utf-8", path); file.Add("path", path); files.Add(file); path = new BEncodedList(); path.Add(new BEncodedString("subfolder1")); path.Add(new BEncodedString("subfolder2")); path.Add(new BEncodedString("file4.txt")); file = new BEncodedDictionary(); file.Add("sha1", new BEncodedString(sha.ComputeHash(System.Text.Encoding.UTF8.GetBytes("file1 hash1")))); file.Add("ed2k", new BEncodedString(sha.ComputeHash(System.Text.Encoding.UTF8.GetBytes("file1 hash2")))); file.Add("length", new BEncodedNumber(80000)); file.Add("md5sum", new BEncodedString(sha.ComputeHash(System.Text.Encoding.UTF8.GetBytes("file1 hash3")))); file.Add("path.utf-8", path); file.Add("path", path); files.Add(file); return(files); }
public void DecodeList() { // List of String var list = new BEncodedList(); foreach (var p in peers) list.Add((BEncodedString) p.CompactPeer()); VerifyDecodedPeers(Peer.Decode(list)); }
/// <summary> /// /// </summary> public void Request() { string encoded_hash = Torrent.GetEncodedInfoHash(); //construction de la requête vers le tracker StringBuilder builder = new StringBuilder(Tracker.Url); builder.AppendFormat("?info_hash={0}", encoded_hash); builder.Append("&peer_id=adkiepeycosozpsngtoi"); builder.Append("&uploaded=0"); builder.Append("&downloaded=0"); builder.AppendFormat("&compact={0}", Compact ? 1 : 0); builder.Append("&left=120000"); builder.Append("&event=started"); builder.Append("&port=6881"); //création de la requête GET HttpWebRequest request = (HttpWebRequest)WebRequest.Create(builder.ToString()); request.Method = "GET"; //envoi de la requête using (WebResponse response = request.GetResponse()) { //récupération de la réponse using (Stream stream = response.GetResponseStream()) { using (var reader = new StreamReader(stream, Encoding.Default)) { string responseText = reader.ReadToEnd(); byte[] data = Encoding.Default.GetBytes(responseText); BEncoding encoding = new BEncoding(data); BEncodedDictionary dictionary = (BEncodedDictionary)encoding.Decode(); Complete = (BEncodedInteger)dictionary["complete"]; Incomplete = (BEncodedInteger)dictionary["incomplete"]; Interval = (BEncodedInteger)dictionary["interval"]; // la liste des peers peut être soit une liste, soit une chaine simplifiée en big endian if (dictionary["peers"] is BEncodedList) { BEncodedList peers = (BEncodedList)dictionary["peers"]; } else if (dictionary["peers"] is BEncodedString) { byte[] peers = Encoding.Default.GetBytes((BEncodedString)dictionary["peers"]); for (int i = 0; i < peers.Length; i = i + 6) { byte[] ip = new byte[4]; byte[] port = new byte[2]; Array.Copy(peers, i, ip, 0, 4); Array.Copy(peers, i + 4, port, 0, 2); Array.Reverse(port); IPEndPoint ipEndPoint = new IPEndPoint(new IPAddress(ip), BitConverter.ToUInt16(port, 0)); Peer peer = new Peer(ipEndPoint); Peers.Add(peer); } } } } } }
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); } } }
public void Add(BEncodedList nodes) { Add(Node.FromCompactNode(nodes)); }