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; }
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); }
/// <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)); }
/// <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)); }
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); } } }
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 BEncodedValue Decode(RawReader reader) => Decode(reader, reader.ReadByte());
static BEncodedDictionary DecodeDictionary(RawReader reader) => DecodeDictionary(reader, reader.StrictDecoding);
/// <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)); }
/// <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)); }