internal static (BEncodedDictionary torrent, InfoHash infohash) DecodeTorrent(RawReader reader) { var torrent = new BEncodedDictionary(); if (reader.ReadByte() != 'd') { throw new BEncodingException("Invalid data found. Aborting"); // Remove the leading 'd' } int read; InfoHash infoHash = null; // We can save a few resizes and array copies if we pre-allocate // a buffer and then get the memory stream to write to it. We // can trivially pass the final set of bytes to the hash function then. byte[] capturedDataBytes = null; MemoryStream capturedDataStream = null; while ((read = reader.ReadByte()) != -1 && read != 'e') { BEncodedValue value; var key = (BEncodedString)Decode(reader, read); // keys have to be BEncoded strings if ((read = reader.ReadByte()) == 'd') { if (InfoKey.Equals(key)) { capturedDataBytes = new byte[reader.Length - reader.Position]; capturedDataStream = new MemoryStream(capturedDataBytes, true); capturedDataStream.WriteByte((byte)'d'); reader.BeginCaptureData(capturedDataStream); } value = DecodeDictionary(reader, reader.StrictDecoding); if (InfoKey.Equals(key)) { reader.EndCaptureData(); using var hasher = SHA1.Create(); infoHash = new InfoHash(hasher.ComputeHash(capturedDataBytes, 0, (int)capturedDataStream.Position)); } } else { value = Decode(reader, read); // the value is a BEncoded value } torrent.Add(key, value); } if (read != 'e') // remove the trailing 'e' { throw new BEncodingException("Invalid data found. Aborting"); } return(torrent, infoHash); }
internal static BEncodedDictionary DecodeTorrent(RawReader reader) { var torrent = new BEncodedDictionary(); if (reader.ReadByte() != 'd') { throw new BEncodingException("Invalid data found. Aborting"); // Remove the leading 'd' } int read; while ((read = reader.ReadByte()) != -1 && read != 'e') { BEncodedValue value; var key = (BEncodedString)Decode(reader, read); // keys have to be BEncoded strings if ((read = reader.ReadByte()) == 'd') { value = DecodeDictionary(reader, InfoKey.Equals(key)); } else { value = Decode(reader, read); // the value is a BEncoded value } torrent.Add(key, value); } if (read != 'e') // remove the trailing 'e' { throw new BEncodingException("Invalid data found. Aborting"); } return(torrent); }
public static (BEncodedDictionary torrent, RawInfoHashes infohashes) DecodeTorrent(Stream reader) { var torrent = new BEncodedDictionary(); if (reader.ReadByte() != 'd') { throw new BEncodingException("Invalid data found. Aborting"); // Remove the leading 'd' } int read; byte[]? infohashSHA1 = null; byte[]? infohashSHA256 = null; while ((read = reader.ReadByte()) != -1) { if (read == 'e') { return(torrent, new RawInfoHashes(infohashSHA1, infohashSHA256)); } if (read < '0' || read > '9') { throw new BEncodingException("Invalid key length"); } BEncodedValue value; var key = (BEncodedString)Decode(reader, false, read); // keys have to be BEncoded strings if ((read = reader.ReadByte()) == 'd') { if (InfoKey.Equals(key)) { using var sha1Reader = new HashingReader(reader, (byte) 'd', SHA1.Create()); using var sha256Reader = new HashingReader(sha1Reader, (byte) 'd', SHA256.Create()); value = DecodeDictionary(sha256Reader, false); infohashSHA1 = sha1Reader.TransformFinalBlock(); infohashSHA256 = sha256Reader.TransformFinalBlock(); } else { value = DecodeDictionary(reader, false); } } else { value = Decode(reader, false, read); } torrent.Add(key, value); } throw new BEncodingException("Invalid data found. Aborting"); }