using System; namespace MonoTorrent { public class Hashes { #region Constants /// /// Hash code length (in bytes) /// internal static readonly int HashCodeLength = 20; #endregion #region Private Fields private int count; private byte[] hashData; #endregion Private Fields #region Properties /// /// Number of Hashes (equivalent to number of Pieces) /// public int Count { get { return this.count; } } #endregion Properties #region Constructors internal Hashes(byte[] hashData, int count) { this.hashData = hashData; this.count = count; } #endregion Constructors #region Methods /// /// Determine whether a calculated hash is equal to our stored hash /// /// Hash code to check /// Index of hash/piece to verify against /// true iff hash is equal to our stored hash, false otherwise public bool IsValid(byte[] hash, int hashIndex) { if (hash == null) throw new ArgumentNullException("hash"); if (hash.Length != HashCodeLength) throw new ArgumentException(string.Format("Hash must be {0} bytes in length", HashCodeLength), "hash"); if (hashIndex < 0 || hashIndex > this.count) throw new ArgumentOutOfRangeException("hashIndex", string.Format("hashIndex must be between 0 and {0}", this.count)); int start = hashIndex * HashCodeLength; for (int i = 0; i < HashCodeLength; i++) if (hash[i] != this.hashData[i + start]) return false; return true; } /// /// Returns the hash for a specific piece /// /// Piece/hash index to return /// byte[] (length HashCodeLength) containing hashdata public byte[] ReadHash(int hashIndex) { if (hashIndex < 0 || hashIndex >= this.count) throw new ArgumentOutOfRangeException("hashIndex"); // Read out our specified piece's hash data byte[] hash = new byte[HashCodeLength]; Buffer.BlockCopy(this.hashData, hashIndex * HashCodeLength, hash, 0, HashCodeLength); return hash; } #endregion Methods } }