public static Metainfo FromBytes(byte[] bytes) { BencodedValue decoded = Bencoder.Decode(bytes); Metainfo metainfo = DecodeMetainfo(decoded); return(metainfo); }
private static void Handle(FileHash hash, PeerHash peer, byte[] payload, Action <FileHash, PeerHash, NetworkAddress[]> callback) { BencodedValue value = Bencoder.Decode(payload); byte[] added = value.Find("added", x => x?.Data?.GetBytes()); List <NetworkAddress> peers = new List <NetworkAddress>(); if (added != null) { for (int i = 0; i < added.Length; i += 6) { string host = GetHost(added, i); int port = GetPort(added, i); if (port > 0) { peers.Add(new NetworkAddress(host, port)); } } } if (added?.Length > 0) { callback(hash, peer, peers.ToArray()); } }
public static BencodedValue GetBencoded(this NetworkIncomingMessage incoming) { byte[] binary = incoming.ToBytes(6); BencodedValue bencoded = Bencoder.Decode(binary); return(bencoded); }
public Metainfo ToMetainfo(out byte[] bytes) { BencodedValue entries = Build(); bytes = Bencoder.Encode(entries); return(MetainfoFactory.FromBytes(bytes)); }
public void OnMessageSent(FileHash hash, PeerHash peer, byte[] payload) { BencodedValue bencoded = Bencoder.Decode(payload); int? message = bencoded.Find("msg_type", x => x?.ToInt32()); int? piece = bencoded.Find("piece", x => x?.ToInt32()); int? size = bencoded.Find("total_size", x => x?.ToInt32()); if (message == 0 && piece != null) { hooks.CallMetadataRequestSent(hash, peer, piece.Value); } if (message == 1 && size != null) { hooks.CallMetadataMeasured(hash, peer, size.Value); } if (message == 1 && piece != null) { byte[] content = Bytes.Copy(payload, bencoded.Data.Length); hooks.MetadataPieceSent(hash, peer, piece.Value, content); } if (message == 2 && piece != null) { hooks.CallMetadataRejectSent(hash, peer, piece.Value); } }
public static void SendMetadataRequest(this CoordinatorService glue, PeerHash peer, int piece) { BencodedValue bencoded = new BencodedValue { Dictionary = new[] { new BencodedEntry { Key = new BencodedValue { Text = new BencodedText("msg_type") }, Value = new BencodedValue { Number = new BencodedNumber(0) } }, new BencodedEntry { Key = new BencodedValue { Text = new BencodedText("piece") }, Value = new BencodedValue { Number = new BencodedNumber(piece) } } } }; glue.SendExtension(peer, MetadataPlugin.Name, Bencoder.Encode(bencoded)); }
private void SerializeDRecord(Bencoder e, DRecord rec) { e.StartDRecord(); foreach (var kvp in rec.Values) { e.ByteString(TextEncoding.GetBytes(kvp.Key)); if (kvp.Value is DNumber) { SerializeDNumber(e, (DNumber)kvp.Value); } else if (kvp.Value is DString) { SerializeDString(e, (DString)kvp.Value); } else /* kvp.Value is DRecord */ { Debug.Assert(kvp.Value is DRecord); SerializeDRecord(e, (DRecord)kvp.Value); } } e.FinishDRecord(); }
public void ExtractInfoHash() { Bencoder bc = new Bencoder(); MnlMessage msg = new MnlMessage .Builder(ParseTest.ConvertHexStringToByteArray("64313a6164323a696432303a7200ee612a3d17f22d721a8019317eb27c7039c9393a696e666f5f6861736832303af6ef92f7cfa792c050fef70c405ded104771553d363a6e6f7365656469316565313a71393a6765745f7065657273313a74343a9b9427a4313a76343a5554ab14313a79313a7165")) .Build(); MnlMessage myMsg = new MnlMessage .Builder(ParseTest.ConvertHexStringToByteArray("64313a74323a3032313a79313a71313a71393a6765745f7065657273313a6164323a696432303a09dc0cea8478d7f285ef674c6a2f931ae3b603f4393a696e666f5f6861736832303a3f4f40163040223f3f063f3a562f603e3f543f3f6565")) .Build(); Dictionary <string, object> decoded = (Dictionary <string, object>)bc.DecodeElement(ParseTest.ConvertHexStringToByteArray("64313a6164323a696432303ab2dfb21aa9b31c00cdca99bcd9232a7facbc76e2393a696e666f5f6861736832303aa44f7b0766a4e53ebfc0cf79fa9c82778b88d94765313a71393a6765745f7065657273313a74343a67707588313a79313a7165")); Dictionary <string, object> decodedMy = (Dictionary <string, object>)bc.DecodeElement(ParseTest.ConvertHexStringToByteArray("64313a74323a3034313a79313a71313a71393a6765745f7065657273313a6164323a696432303ae36f5d8ef6928691d9696e02d025e3b8f1a08ca2393a696e666f5f6861736832303a139f69de76a07790ec3ad31cbc3bd5d9058716006565")); var infoHash = Encoding.UTF8.GetBytes((string)((Dictionary <string, object>)decoded["a"])["info_hash"]); var bytes = ParseTest.ConvertHexStringToByteArray("3F4F40163040223F3F063F3A562F603E3F543F3F"); //CollectionAssert.AreEqual(infoHash, bytes); SoapHexBinary hex = new SoapHexBinary(infoHash); Debug.WriteLine($"Info hash: {hex.ToString()} "); }
public Builder(byte[] msg) { Bencoder bencoder = new Bencoder(); var decodedMsg = bencoder.DecodeElement(msg); Dictionary <string, object> msgFields = (Dictionary <string, object>)decodedMsg; _msg = new MnlMessage(); try { _msg.TranId = Bencoder.DefEncoding.GetString((byte[])msgFields["t"]); } catch (KeyNotFoundException) { throw new MalformedPacketException("t"); } try { _msg.Type = (MessageType)(Bencoder.DefEncoding.GetString((byte[])msgFields["y"])[0]); } catch (KeyNotFoundException) { throw new MalformedPacketException("y"); } if (msgFields.ContainsKey("q")) { _msg.QueryType = Bencoder.DefEncoding.GetString((byte[])msgFields["q"]); } switch (_msg.Type) { case MessageType.Query: try { _msg.Payload = (Dictionary <string, object>)msgFields["a"]; } catch (KeyNotFoundException) { throw new MalformedPacketException("a"); } break; case MessageType.Response: try { _msg.Payload = (Dictionary <string, object>)msgFields["r"]; } catch (KeyNotFoundException) { throw new MalformedPacketException("r"); } break; case MessageType.Error: try { List <object> errList = (List <object>)msgFields["e"]; int codeIdx = errList[0] is int? 0 : 1; _msg.ErrorCode = (ErrorType)errList[codeIdx]; if (errList.Count > 1) { _msg.ErrorMessage = Bencoder.DefEncoding.GetString((byte[])errList[codeIdx == 0 ? 1 : 0]); //TODO: ??? } } catch (KeyNotFoundException) { throw new MalformedPacketException("e"); } return; } _msg.OriginatorId = new Id((byte[])_msg.Payload["id"]); }
public byte[] ToBytes() { BencodedValue entries = Build(); byte[] bytes = Bencoder.Encode(entries); return(bytes); }
public Extended GetHandshake() { BencodedValue encoded = more.Encode(metadata?.Size); byte[] binary = Bencoder.Encode(encoded); return(new Extended(0, binary)); }
public void ShouldDecodeAsInteger() { byte[] data = Encoding.ASCII.GetBytes("i10e"); BencodedValue value = Bencoder.Decode(data); value.Should().NotBeNull(); value.Number.Should().NotBeNull(); value.Number.ToInt32().Should().Be(10); }
public void OnHandshake(FileHash hash, PeerHash peer, byte[] payload) { BencodedValue bencoded = Bencoder.Decode(payload); int? size = bencoded.Find("metadata_size", x => x?.ToInt32()); if (size != null) { hooks.CallMetadataMeasured(hash, peer, size.Value); } }
public void ParseFindNode() { string findNodeMsg = "64313a6164323a696432303a5fa2a8ea6689e6beaa61b93196b10f4404dac592363a74617267657432303a5fa2a8ea6689e6beaa61b93196b10f4404dac59265313a71393a66696e645f6e6f6465313a74323aaf9e313a76343a4c540100313a79313a7165"; Bencoder bc = new Bencoder(); byte[] msgAsBytes = ConvertHexStringToByteArray(findNodeMsg); string asciiMsg = Encoding.ASCII.GetString(msgAsBytes); Dictionary <string, object> fields = (Dictionary <string, object>)bc.DecodeElement(msgAsBytes); }
public FileHash ToHash() { BencodedValue entries = Build(); byte[] bytes = Bencoder.Encode(entries); Metainfo metainfo = MetainfoFactory.FromBytes(bytes); FileHash hash = metainfo.Hash; return(hash); }
public void ParsePing() { string pingMsg = "64313a6164323a696432303a5fa2a2809655927cbbe6fdab912c88e59a4630b065313a71343a70696e67313a74323a0136313a76343a4c540101313a79313a7165"; string unicodePingMsg = Encoding.ASCII.GetString(ConvertHexStringToByteArray(pingMsg)); string myPingMsg = "64313a74323a3032313a79313a71313a71343a70696e67313a6164323a696432303aefbfbd55efbfbd4a43efbfbd23efbfbdefbfbd20efbfbdefbfbdefbfbdefbfbd113738efbfbdefbfbd176565"; string unicodeMyPingMsg = Encoding.ASCII.GetString(ConvertHexStringToByteArray(myPingMsg)); Bencoder bc = new Bencoder(); Dictionary <string, object> fields = (Dictionary <string, object>)bc.DecodeElement(ConvertHexStringToByteArray(pingMsg)); Dictionary <string, object> myfields = (Dictionary <string, object>)bc.DecodeElement(ConvertHexStringToByteArray(myPingMsg)); int boop = 1; }
public static MetainfoFile FromFile(string path) { byte[] bytes = File.ReadAllBytes(path); BencodedValue decoded = Bencoder.Decode(bytes); BencodedValue info = decoded.Find("info", x => x); Metainfo metainfo = DecodeMetainfo(info); string[] trackers = FindTrackers(decoded); return(new MetainfoFile(metainfo, trackers)); }
public Metainfo(byte[] data, Encoding encoding) { _defaultEncoding = encoding; _bencoder = Bencoder.Build(); var metainfoDict = _bencoder.Decode(data); var infoDict = metainfoDict[InfoDictionaryKey]; PieceLength = infoDict[PieceLengthKey]; // ReSharper disable once PossibleLossOfFraction PiecesHash = infoDict[PiecesKey]; InfoHash = CalcInfoHashBytes(infoDict); Announces = GetAnnounces(metainfoDict); Files = GetFiles(infoDict); TotalLength = CalcTotalLength(Files); PiecesCount = (int)Math.Ceiling((double)(TotalLength / PieceLength)) + 1; }
/// <summary> /// Requests peer and other info from tracker /// </summary> /// <param name="evnt">Client event</param> /// <param name="compact">Whether tracker response should be compact</param> /// <returns>Tracker response</returns> private Dictionary <string, object> QueryTracker(ClientEvent evnt = ClientEvent.None, bool compact = true) { BtClientStats clientStats = Client.GetStats(); NameValueCollection httpRqArgs = new NameValueCollection(); httpRqArgs.Add("info_hash", HttpUtility.UrlEncode(Client.GetInfoHash())); httpRqArgs.Add("peer_id", HttpUtility.UrlEncode(Client.GetPeerID())); httpRqArgs.Add("uploaded", clientStats.Uploaded.ToString()); httpRqArgs.Add("downloaded", clientStats.Downloaded.ToString()); httpRqArgs.Add("left", clientStats.Left.ToString()); httpRqArgs.Add("compact", compact ? "1" : "0"); httpRqArgs.Add("event", evnt.ToString()); if (_trackerId != null) { httpRqArgs.Add("trackerid", _trackerId); } if (_key != null) { httpRqArgs.Add("key", _key); } string rqUrl = Url + ToQueryString(httpRqArgs); Debug.WriteLine($"Tracker request: {rqUrl}"); HttpWebRequest httpRq = (HttpWebRequest)WebRequest.Create(rqUrl); httpRq.UserAgent = UserAgent; HttpWebResponse httpRs = (HttpWebResponse)httpRq.GetResponse(); if (httpRs.StatusCode == HttpStatusCode.OK) { MemoryStream httpRsStream = new MemoryStream(httpRs.ContentLength != -1 ? (int)httpRs.ContentLength : 0); httpRs.GetResponseStream()?.CopyTo(httpRsStream); return((Dictionary <string, object>)Bencoder.DecodeElement(httpRsStream.ToArray())); } return(null); }
private void ListenResponses() { new Thread(() => { Bencoder bencoder = new Bencoder(); while (!_myCancelTokenSrc.IsCancellationRequested) { int len = ParseInt(ReadMsgSync(4)); byte[] incMsg = ReadMsgSync(len); var decoded = (Dictionary <string, object>)bencoder.DecodeElement(incMsg); string action = (string)decoded["action"]; switch (action) { case "sysout": _myPool.Add(new Peer(IPAddress.Parse((string)decoded["ip"]), int.Parse((string)decoded["port"]))); break; } } }).Start(); }
public static void SendPeers(this CoordinatorService glue, PeerHash peer, params NetworkAddress[] remotes) { BencodedValue bencoded = new BencodedValue { Dictionary = new[] { new BencodedEntry { Key = new BencodedValue { Text = new BencodedText("added") }, Value = new BencodedValue { Data = ToData(remotes) } } } }; glue.SendExtension(peer, PeersPlugin.Name, Bencoder.Encode(bencoded)); }
public static void SendMetadataPiece(this CoordinatorService glue, PeerHash peer, int piece, int total, byte[] data) { BencodedValue bencoded = new BencodedValue { Dictionary = new[] { new BencodedEntry { Key = new BencodedValue { Text = new BencodedText("msg_type") }, Value = new BencodedValue { Number = new BencodedNumber(1) } }, new BencodedEntry { Key = new BencodedValue { Text = new BencodedText("piece") }, Value = new BencodedValue { Number = new BencodedNumber(piece) } }, new BencodedEntry { Key = new BencodedValue { Text = new BencodedText("total_size") }, Value = new BencodedValue { Number = new BencodedNumber(total) } } } }; byte[] payload = Bencoder.Encode(bencoded); Bytes.Append(ref payload, data); glue.SendExtension(peer, MetadataPlugin.Name, payload); }
public Metainfo(byte[] data, Encoding encoding) { Protocol = encoding.GetBytes("BitTorrent protocol"); _encoding = encoding; _bencoder = new Bencoder(); var metainfoDict = (Dictionary <string, object>)_bencoder.DecodeElement(data); var infoDict = (Dictionary <string, object>)metainfoDict[InfoDictionaryKey]; PieceLength = (int)infoDict[PieceLengthKey]; PiecesHash = (byte[])infoDict[PiecesKey]; InfoHash = CalcInfoHashBytes(infoDict); Nodes = GetNodes(metainfoDict); Announces = GetAnnounces(metainfoDict); if (metainfoDict.ContainsKey(AnnounceKey)) { Announces.Add(_bencoder.Encoding.GetString((byte[])metainfoDict[AnnounceKey])); } Files = GetFiles(infoDict); TotalLength = CalcTotalLength(Files); PiecesCount = (int)Math.Ceiling((double)(TotalLength / PieceLength)); }
private void InvokeGetPeers(byte[] infohash, bool fast, bool nocache) { lock (__peersSearchLck) { Dictionary <string, Object> argsDict = new Dictionary <string, object>(); List <Object> args = new List <Object> { GETPEERS_KEY, new System.Runtime.Remoting.Metadata.W3cXsd2001.SoapHexBinary(infohash).ToString() }; if (fast) { args.Add("-fast"); } if (nocache) { args.Add("-nocache"); } argsDict["arguments"] = args; argsDict["cwd"] = "."; Bencoder beEncoder = new Bencoder(); byte[] bencodedArgs = beEncoder.EncodeElement(argsDict); while (!_myCancelTokenSrc.IsCancellationRequested) { try { _extMnlClientStream.Write(GetInt(bencodedArgs.Length), 0, 4); _extMnlClientStream.Write(bencodedArgs, 0, bencodedArgs.Length); _extMnlClientStream.Flush(); } catch (SocketException se) { Debug.WriteLine($"Can't connect to remote table {se}, waiting 10 secs and trying once more"); Thread.Sleep(10000); continue; } break; } } }
private void AssertEncodesTo(Action<Bencoder> encodingSteps, string expected) { byte[] expectedBytes = Encoding.ASCII.GetBytes(expected); Bencoder e = new Bencoder(); encodingSteps.Invoke(e); byte[] actualBytes = e.Encoded; Utils.AssertBytewiseIdentical(expectedBytes, actualBytes); }
public void TestEncodeEmpty() { Bencoder e = new Bencoder(); Assert.AreEqual(e.Encoded.Length, 0); }
private TcpSocketReceiveCallback OnReceived(TrackerGetHttpEntry entry) { return(received => { if (received.Status == SocketStatus.OK) { context.Queue.Add(() => { byte[] data = Bytes.Copy(entry.Buffer.Data, entry.Buffer.Offset, received.Count); string text = Encoding.ASCII.GetString(data); context.CallPacketReceived(entry.Endpoint, data.Length); if (text.StartsWith(TrackerGetHttpProtocol.ResponseHeader) == false) { context.CallPacketIgnored(entry.Endpoint, data.Length); return; } int counter = 0, position = 0; bool r = false, n = false; for (int i = 0; i < data.Length; i++) { if (data[i] == '\r') { r = true; counter++; continue; } if (data[i] == '\n') { n = true; counter++; continue; } if (counter == 4 && r && n) { position = i; break; } if (counter == 2 && !(r && n)) { position = i; break; } counter = 0; } if (position == 0) { context.CallPacketIgnored(entry.Endpoint, data.Length); return; } BencodedValue decoded = Bencoder.Decode(data, position); if (decoded.Dictionary == null) { context.CallPacketIgnored(entry.Endpoint, data.Length); return; } string failure = decoded.Find("failure reason", x => x?.Text?.GetString()); if (failure != null) { context.CallFailed(entry.Address, entry.Request.Hash, failure); return; } int?interval = decoded.Find("interval", x => x?.ToInt32()); BencodedValue peers = decoded.Find("peers", x => x); if (interval != null && peers.Text != null && peers.Text.Length % 6 == 0) { List <NetworkAddress> result = new List <NetworkAddress>(peers.Text.Length / 6); byte[] bytes = peers.Data.GetBytes(); for (int i = 0; i < bytes.Length; i += 6) { int port = Bytes.ReadUInt16(bytes, i + 4); StringBuilder address = new StringBuilder(); address.Append(bytes[i].ToString()); address.Append('.'); address.Append(bytes[i + 1].ToString()); address.Append('.'); address.Append(bytes[i + 2].ToString()); address.Append('.'); address.Append(bytes[i + 3].ToString()); if (port > 0) { result.Add(new NetworkAddress(address.ToString(), port)); } } collection.Remove(entry.Socket); entry.Callback.Invoke(TimeSpan.FromSeconds(interval.Value)); context.CallAnnounced(entry.Address, entry.Request.Hash, TimeSpan.FromSeconds(interval.Value), result.ToArray()); } }); } }); }
public void ParseProblematicMsg() { string problematicMsg = "d1:rd2:id20:????g????r=)??HWu5:nodes208:?Jk??\" ??? jm ?? (???[?3????[E?{??ZU?x??,???????ln?|^L@??cxQkXT/???c??=Z??2?U??H??m?*Y?D?? K????????V???('.??= ??B96?????h?S? V????t??????q? j???O?|^?b? p???????????I??"; var decoded = new Bencoder().DecodeElement(Encoding.ASCII.GetBytes(problematicMsg)); }
public void ParseMsgWithProblematicList() { byte[] problematicMsg = ParseTest.ConvertHexStringToByteArray("64313A7264323A696432303A30643513245B078D06870AA59DB1F7A21EC41608353A746F6B656E323A6778363A76616C7565736C6565313A74323A4635313A79313A7265"); var decoded = new Bencoder().DecodeElement(problematicMsg); }
private void SerializeDString(Bencoder e, DString s) { e.StartDString().ByteString(TextEncoding.GetBytes(s.Value)).FinishDString(); }
public byte[] Encode(Message msg) { Bencoder encoder = new Bencoder(); encoder.StartDictionary(); encoder.ByteString(TextEncoding.GetBytes(SequenceNumberFieldName)) .Integer(msg.SequenceNumber) .ByteString(TextEncoding.GetBytes(AckNumberFieldName)) .Integer(msg.AckNumber) .ByteString(TextEncoding.GetBytes(OpCodeFieldName)) .Integer((long)msg.OpCode); foreach (string k in msg.Attributes.Keys) { encoder.ByteString(TextEncoding.GetBytes(k)); object value = msg.Attributes[k]; if (typeof(long).IsAssignableFrom(value.GetType())) { encoder.Integer((long)value); } else if (value is DNumber) { SerializeDNumber(encoder, (DNumber)value); } else if (value is string) { encoder.ByteString(TextEncoding.GetBytes((string)value)); } else if (value is DString) { SerializeDString(encoder, (DString)value); } else if (value is DRecord) { SerializeDRecord(encoder, (DRecord)value); } else { throw new NotImplementedException(); } } encoder.FinishDictionary(); return encoder.Encoded; }
private void SerializeDNumber(Bencoder e, DNumber n) { e.StartDNumber().Number(n.Value).FinishDNumber(); }