public override void Decode(byte[] buffer, int offset, int length)
        {
            BEncodedValue val;
            using (var reader = new RawReader(new MemoryStream(buffer, offset, length, false), false))
            {
                var d = BEncodedValue.Decode<BEncodedDictionary>(reader);
                var totalSize = 0;

                if (d.TryGetValue(MessageTypeKey, out val))
                    MetadataMessageType = (eMessageType) ((BEncodedNumber) val).Number;
                if (d.TryGetValue(PieceKey, out val))
                    Piece = (int) ((BEncodedNumber) val).Number;
                if (d.TryGetValue(TotalSizeKey, out val))
                {
                    totalSize = (int) ((BEncodedNumber) val).Number;
                    MetadataPiece = new byte[Math.Min(totalSize - Piece*BlockSize, BlockSize)];
                    reader.Read(MetadataPiece, 0, MetadataPiece.Length);
                }
            }
        }
        /// <summary>
        /// Decodes a BEncoded number from the supplied RawReader
        /// </summary>
        /// <param name="reader">RawReader containing a BEncoded Number</param>
        internal override void DecodeInternal(RawReader reader)
        {
            if (reader == null)
            {
                throw new ArgumentNullException("reader");
            }

            try
            {
                if (reader.ReadByte() != 'i')              // remove the leading 'i'
                {
                    throw new BEncodingException("Invalid data found. Aborting.");
                }

                int letter;
                while (((letter = reader.PeekChar()) != -1) && letter != 'e')
                {
                    if (letter < '0' || letter > '9')
                    {
                        throw new BEncodingException("Invalid number found.");
                    }
                    number = number * 10 + (letter - '0');
                    reader.ReadChar();
                }
                if (reader.ReadByte() != 'e')        //remove the trailing 'e'
                {
                    throw new BEncodingException("Invalid data found. Aborting.");
                }
            }
            catch (BEncodingException ex)
            {
                throw new BEncodingException("Couldn't decode number", ex);
            }
            catch
            {
                throw new BEncodingException("Couldn't decode number");
            }
        }
        /// <summary>
        /// Decodes a BEncoded number from the supplied RawReader
        /// </summary>
        /// <param name="reader">RawReader containing a BEncoded Number</param>
        internal override void DecodeInternal(RawReader reader)
        {
            int sign = 1;

            if (reader == null)
            {
                throw new ArgumentNullException("reader");
            }

            if (reader.ReadByte() != 'i')                          // remove the leading 'i'
            {
                throw new BEncodingException("Invalid data found. Aborting.");
            }

            if (reader.PeekByte() == '-')
            {
                sign = -1;
                reader.ReadByte();
            }

            int letter;

            while (((letter = reader.PeekByte()) != -1) && letter != 'e')
            {
                if (letter < '0' || letter > '9')
                {
                    throw new BEncodingException("Invalid number found.");
                }
                number = number * 10 + (letter - '0');
                reader.ReadByte();
            }
            if (reader.ReadByte() != 'e')                    //remove the trailing 'e'
            {
                throw new BEncodingException("Invalid data found. Aborting.");
            }

            number *= sign;
        }
Esempio n. 4
0
        static BEncodedValue Decode(RawReader reader, int read)
        {
            BEncodedValue data;

            switch (read)
            {
            case ('i'):                             // Integer
                data = DecodeNumber(reader);
                break;

            case ('d'):                             // Dictionary
                data = DecodeDictionary(reader);
                break;

            case ('l'):                             // List
                data = DecodeList(reader);
                break;

            case ('1'):                             // String
            case ('2'):
            case ('3'):
            case ('4'):
            case ('5'):
            case ('6'):
            case ('7'):
            case ('8'):
            case ('9'):
            case ('0'):
                data = DecodeString(reader, read - '0');
                break;

            default:
                throw new BEncodingException("Could not find what value to decode");
            }

            return(data);
        }
Esempio n. 5
0
 /// <summary>
 /// Special decoding method for torrent files - allows dictionary attributes to be out of order for the
 /// overall torrent file, but imposes strict rules on the info dictionary.
 /// </summary>
 /// <returns></returns>
 public static BEncodedDictionary DecodeTorrent(RawReader reader)
 {
     return(BEncodeDecoder.DecodeTorrent(reader));
 }
Esempio n. 6
0
 /// <summary>
 ///
 /// </summary>
 /// <param name="reader"></param>
 internal override void DecodeInternal(RawReader reader)
 {
     DecodeInternal(reader, reader.StrictDecoding);
 }
 internal abstract void DecodeInternal(RawReader reader);
 public static T Decode <T>(RawReader reader) where T : BEncodedValue
 {
     return((T)BEncodedValue.Decode(reader));
 }
Esempio n. 9
0
        public override void Decode(byte[] buffer, int offset, int length)
        {
            BEncodedValue val;
            using (RawReader reader = new RawReader(new MemoryStream(buffer, offset, length, false), false))
            {
                BEncodedDictionary d = BEncodedDictionary.Decode<BEncodedDictionary>(reader);
                int totalSize;

                if (d.TryGetValue(MessageTypeKey, out val))
                    messageType = (eMessageType)((BEncodedNumber)val).Number;
                if (d.TryGetValue(PieceKey, out val))
                    piece = (int)((BEncodedNumber)val).Number;
                if (d.TryGetValue(TotalSizeKey, out val))
                {
                    totalSize = (int)((BEncodedNumber)val).Number;
                    metadata = new byte[Math.Min(totalSize - piece * BlockSize, BlockSize)];
                    reader.Read(metadata, 0, metadata.Length);
                }
            }
        }
Esempio n. 10
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);
        }
Esempio n. 11
0
 internal static BEncodedValue Decode(RawReader reader)
 => Decode(reader, reader.ReadByte());
Esempio n. 12
0
 static BEncodedDictionary DecodeDictionary(RawReader reader)
 => DecodeDictionary(reader, reader.StrictDecoding);
Esempio n. 13
0
 /// <summary>
 /// Special decoding method for torrent files - allows dictionary attributes to be out of order for the
 /// overall torrent file, but imposes strict rules on the info dictionary.
 /// </summary>
 /// <returns></returns>
 public static (BEncodedDictionary torrent, InfoHash infohash) DecodeTorrent(RawReader reader)
 {
     return(BEncodeDecoder.DecodeTorrent(reader));
 }
Esempio n. 14
0
 /// <summary>
 /// Decode BEncoded data in the given RawReader
 /// </summary>
 /// <param name="reader">The RawReader containing the BEncoded data</param>
 /// <returns>BEncodedValue containing the data that was in the stream</returns>
 public static BEncodedValue Decode(RawReader reader)
 {
     return(BEncodeDecoder.Decode(reader));
 }