Пример #1
0
        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);
        }