Пример #1
0
        private bool GetPieceInfoFromFile(CheckIntegrityCallback callback)
        {
            string pieceFilePath = Config.ApplicationDataDirectory + IO.Path.DirectorySeparatorChar + this.infofile.PieceFileName + ".piece";

            IO.FileInfo pieceFileInfo = new IO.FileInfo(pieceFilePath);
            if (pieceFileInfo.Exists)
            {
                // before we rely on the piece file, do a simple check of file existance and lengths to make sure nothing's changed
                for (int i = 0; i < this.infofile.FileCount; ++i)
                {
                    string path         = this.infofile.GetFileName(i);
                    int    properLength = this.infofile.GetFileLength(i);

                    // TODO: introduce modification time check - requires saving time data in piece file

                    IO.FileInfo fileInfo = new IO.FileInfo(path);
                    if (!fileInfo.Exists)
                    {
                        return(false);                        // a file doesn't exist, do a proper check
                    }
                    long realLength = fileInfo.Length;
                    if (properLength != realLength)
                    {
                        return(false);                        // a file doesn't have a proper length, do a proper check
                    }
                }

                IO.FileStream pieceFile = pieceFileInfo.OpenRead();
                int           numBytes  = this.infofile.PieceCount / 8 + ((this.infofile.PieceCount % 8) > 0 ? 1 : 0);
                byte[]        data      = new byte[numBytes];
                pieceFile.Read(data, 0, data.Length);
                pieceFile.Close();

                this.piecesDownloaded.SetFromRaw(data, 0, data.Length);
                this.piecesDownloaded.SetLength(this.infofile.PieceCount);

                this.numBytesLeft = 0;
                for (int i = 0; i < this.infofile.PieceCount; ++i)
                {
                    if (!this.piecesDownloaded[i])
                    {
                        this.numBytesLeft += this.infofile.GetPieceLength(i);
                    }
                }

                if (callback != null)
                {
                    callback(this, this.infofile.PieceCount - 1, false, 100.0f);
                }

                return(true);
            }
            else
            {
                return(false);
            }
        }
Пример #2
0
        /// <summary>
        /// This *must* be called before any operations are performed. This should be in the constructor, but as it can be a time-consuming process
        /// it was decided against. This analyzes the file to look for which pieces are downloaded, or if the torrent has just started it will create the
        /// new, empty files.
        /// </summary>
        /// <param name="callback">Callback delegate to inform the caller of the progress</param>
        public void CheckIntegrity(bool forced, CheckIntegrityCallback callback)
        {
            // if their already is a piece file in the application directory, load it from there. (unless it is forced where is has to do it)
            if (forced || !GetPieceInfoFromFile(callback))
            {
                int         dataPosition = 0, filePosition = 0;
                int         i    = 0;
                byte[]      data = new byte[this.infofile.GetPieceLength(0)];
                Crypto.SHA1 sha  = Crypto.SHA1CryptoServiceProvider.Create();

                for (int currentFile = 0; currentFile < this.infofile.FileCount; ++currentFile)
                {
                    int    fileLength = this.infofile.GetFileLength(currentFile);
                    string path       = this.infofile.GetFileName(currentFile);

                    IO.FileInfo fileInfo = new IO.FileInfo(path);

                    if (!fileInfo.Exists)
                    {
                        // create the file if it does not exist
                        this.CreateEmptyFile(fileInfo, fileLength);

                        int fileDataLeft = 0;

                        if (dataPosition > 0)
                        {
                            // if dataPosition does not equal zero, meaning we have some of a piece from the last file. This automatically fails,
                            // and we move onto the next piece.
                            i++;
                            fileDataLeft = fileLength - (this.infofile.GetPieceLength(0) - dataPosition);
                        }
                        else
                        {
                            fileDataLeft = fileLength - filePosition;
                        }

                        int numPieces = fileDataLeft / this.infofile.GetPieceLength(0);
                        i += numPieces;
                        if (fileDataLeft % this.infofile.GetPieceLength(0) > 0)
                        {
                            // set the next file's filePosition, and fail the next piece
                            filePosition = this.infofile.GetPieceLength(i) - (fileDataLeft % this.infofile.GetPieceLength(i));
                            i++;
                        }
                        else
                        {
                            filePosition = 0;
                        }

                        dataPosition = 0;

                        if (callback != null)
                        {
                            callback(this, i, false, ((float)(i + 1) / (float)this.infofile.PieceCount) * 100.0f);
                        }

                        // move onto next file
                        continue;
                    }
                    else
                    {
                        // check the length, otherwise truncate it
                        if (fileInfo.Length != fileLength)
                        {
                            this.TruncateFile(fileInfo, fileLength);
                        }

                        // open the file, start checking.
                        IO.FileStream fstream = fileInfo.OpenRead();

                        while (filePosition < fileLength)
                        {
                            int    dataToRead = System.Math.Min(fileLength - filePosition, this.infofile.GetPieceLength(i) - dataPosition);
                            byte[] tempData   = new byte[dataToRead];
                            fstream.Read(tempData, 0, tempData.Length);

                            if (dataToRead + dataPosition >= this.infofile.GetPieceLength(i))
                            {
                                // piece finished
                                System.Array.Copy(tempData, 0, data, dataPosition, dataToRead);
                                sha.ComputeHash(data, 0, this.infofile.GetPieceLength(i));

                                ByteField20 final = new ByteField20(sha.Hash);
                                bool        good  = final.Equals(this.infofile.GetSHADigest(i));

                                if (!good)                                 // if piece is good we can subtract it from the bytes left to download
                                {
                                    numBytesLeft += this.infofile.GetPieceLength(i);
                                }

                                this.piecesDownloaded.Set(i, good);

                                if (callback != null)
                                {
                                    callback(this, i, good, ((float)(i + 1) / (float)this.infofile.PieceCount) * 100.0f);
                                }

                                i++;
                                dataPosition = 0;
                            }
                            else
                            {
                                System.Array.Copy(tempData, 0, data, dataPosition, dataToRead);
                                dataPosition += dataToRead;
                            }

                            filePosition += dataToRead;
                        }

                        filePosition = 0;
                        fstream.Close();
                    }
                }
            }

            if (this.PercentChanged != null)
            {
                this.PercentChanged(this, this.PercentComplete);
            }
        }
Пример #3
0
		/// <summary>
		/// This *must* be called before any operations are performed. This should be in the constructor, but as it can be a time-consuming process
		/// it was decided against. This analyzes the file to look for which pieces are downloaded, or if the torrent has just started it will create the
		/// new, empty files.
		/// </summary>
		/// <param name="callback">Callback delegate to inform the caller of the progress</param>
		public void CheckIntegrity( bool forced, CheckIntegrityCallback callback)
		{
			// if their already is a piece file in the application directory, load it from there. (unless it is forced where is has to do it)
			if ( forced || !GetPieceInfoFromFile(callback))
			{
				int dataPosition = 0, filePosition = 0;
				int i = 0;
				byte[] data = new byte[this.infofile.GetPieceLength(0)];
				Crypto.SHA1 sha = Crypto.SHA1CryptoServiceProvider.Create();

				for (int currentFile=0; currentFile<this.infofile.FileCount; ++currentFile)
				{
					int fileLength = this.infofile.GetFileLength(currentFile);
					string path = this.infofile.GetFileName(currentFile);

					IO.FileInfo fileInfo = new IO.FileInfo(path);
				
					if (!fileInfo.Exists)
					{
						// create the file if it does not exist
						this.CreateEmptyFile(fileInfo, fileLength);

						int fileDataLeft = 0;

						if (dataPosition > 0)
						{
							// if dataPosition does not equal zero, meaning we have some of a piece from the last file. This automatically fails,
							// and we move onto the next piece.
							i++;
							fileDataLeft = fileLength - (this.infofile.GetPieceLength(0) - dataPosition);
						}
						else
							fileDataLeft = fileLength - filePosition;

						int numPieces = fileDataLeft / this.infofile.GetPieceLength(0);
						i += numPieces;
						if (fileDataLeft % this.infofile.GetPieceLength(0) > 0)
						{
							// set the next file's filePosition, and fail the next piece
							filePosition = this.infofile.GetPieceLength(i) - (fileDataLeft % this.infofile.GetPieceLength(i));
							i++;
						}
						else
						{
							filePosition = 0;
						}

						dataPosition = 0;

						if (callback != null)
							callback(this, i, false, ((float)(i+1)/(float)this.infofile.PieceCount) * 100.0f);

						// move onto next file
						continue;
					}
					else
					{
						// check the length, otherwise truncate it
						if (fileInfo.Length != fileLength)
							this.TruncateFile(fileInfo, fileLength);

						// open the file, start checking.
						IO.FileStream fstream = fileInfo.OpenRead();

						while (filePosition < fileLength)
						{
							int dataToRead = System.Math.Min(fileLength - filePosition, this.infofile.GetPieceLength(i) - dataPosition);
							byte[] tempData = new byte[dataToRead];
							fstream.Read(tempData, 0, tempData.Length);
					
							if (dataToRead + dataPosition >= this.infofile.GetPieceLength(i))
							{
								// piece finished
								System.Array.Copy(tempData, 0, data, dataPosition, dataToRead);
								sha.ComputeHash(data, 0, this.infofile.GetPieceLength(i));

								ByteField20 final = new ByteField20(sha.Hash);
								bool good = final.Equals( this.infofile.GetSHADigest(i) );
				
								if (!good) // if piece is good we can subtract it from the bytes left to download
									numBytesLeft += this.infofile.GetPieceLength(i);
					
								this.piecesDownloaded.Set(i, good);

								if (callback != null)
									callback(this, i, good, ((float)(i+1)/(float)this.infofile.PieceCount) * 100.0f);

								i++;
								dataPosition = 0;
							}
							else
							{
								System.Array.Copy(tempData, 0, data, dataPosition, dataToRead);
								dataPosition += dataToRead;
							}

							filePosition += dataToRead;
						}

						filePosition = 0;
						fstream.Close();
					}
				}
			}

			if (this.PercentChanged != null)
				this.PercentChanged(this, this.PercentComplete);
		}
Пример #4
0
		private bool GetPieceInfoFromFile(CheckIntegrityCallback callback)
		{
			string pieceFilePath = Config.ApplicationDataDirectory + IO.Path.DirectorySeparatorChar + this.infofile.PieceFileName + ".piece";
			IO.FileInfo pieceFileInfo = new IO.FileInfo(pieceFilePath);
			if (pieceFileInfo.Exists)
			{
				// before we rely on the piece file, do a simple check of file existance and lengths to make sure nothing's changed
				for (int i=0; i<this.infofile.FileCount; ++i)
				{
					string path = this.infofile.GetFileName(i);
					int properLength = this.infofile.GetFileLength(i);

					// TODO: introduce modification time check - requires saving time data in piece file

					IO.FileInfo fileInfo = new IO.FileInfo(path);
					if (!fileInfo.Exists)
						return false; // a file doesn't exist, do a proper check

					long realLength = fileInfo.Length;
					if (properLength != realLength)
						return false; // a file doesn't have a proper length, do a proper check
				}

				IO.FileStream pieceFile = pieceFileInfo.OpenRead();
				int numBytes = this.infofile.PieceCount/8 + ((this.infofile.PieceCount % 8) > 0 ? 1 : 0);
				byte[] data = new byte[numBytes];
				pieceFile.Read(data, 0, data.Length);
				pieceFile.Close();

				this.piecesDownloaded.SetFromRaw( data, 0, data.Length );
				this.piecesDownloaded.SetLength(this.infofile.PieceCount);

				this.numBytesLeft = 0;
				for (int i=0; i<this.infofile.PieceCount; ++i)
				{
					if (!this.piecesDownloaded[i])
						this.numBytesLeft += this.infofile.GetPieceLength(i);
				}

				if (callback != null)
					callback(this, this.infofile.PieceCount-1, false, 100.0f);

				return true;
			}
			else
				return false;
		}