예제 #1
0
        /// <summary>
        /// Helper thread method to start the connection to peers
        /// </summary>
        /// <param name="state"></param>
        private void StartPeerConnectionThread(System.IAsyncResult result)
        {
            object[]        objs = (object[])result.AsyncState;
            Sockets.Socket  socket = (Sockets.Socket)objs[0];
            PeerInformation peerinfo = (PeerInformation)objs[1];
            ByteField20     infoDigest = new ByteField20(), peerId = new ByteField20();

            Sockets.NetworkStream netStream;

            try
            {
                socket.EndConnect(result);

                netStream = new Sockets.NetworkStream(socket, true);

                // send handshake info
                PeerProtocol.SendHandshake(netStream, this.infofile.InfoDigest);
                PeerProtocol.ReceiveHandshake(netStream, ref infoDigest);
                PeerProtocol.SendPeerId(netStream, this.mSession.LocalPeerID);

                if (!PeerProtocol.ReceivePeerId(netStream, ref peerId))
                {                 // NAT check
                    socket.Close();
                    return;
                }

                // check info digest matches and we are not attempting to connect to ourself
                if (infoDigest.Equals(this.infofile.InfoDigest) && !peerId.Equals(this.mSession.LocalPeerID))
                {
                    peerinfo.ID = peerId;
                    this.AddPeer(socket, netStream, peerinfo);
                }
                else                 // info digest doesn't match, close the connection
                {
                    socket.Close();
                }
            }
            catch (System.Exception e)
            {
                Config.LogException(e);
                // die if the connection failed
                if (socket != null)
                {
                    socket.Close();
                }
                return;
            }
        }
예제 #2
0
        private void OnAccept(System.IAsyncResult result)
        {
            Sockets.Socket socket;

            try
            {
                // Accept connections from other peers, find the appropriate torrent and add the peer to it
                socket = this.mListener.EndAccept(result);
            }
            catch (System.Exception)
            {
                if (this.mListener != null)
                {
                    this.mListener.Close();
                }
                this.mListener = null;
                return;
            }

            try
            {
                ByteField20           infoDigest = new ByteField20(), peerId = new ByteField20();
                Sockets.NetworkStream netStream = new Sockets.NetworkStream(socket, true);

                PeerProtocol.ReceiveHandshake(netStream, ref infoDigest);

                Torrent torrent = this.FindTorrent(infoDigest);

                if (torrent != null)
                {
                    // found it, finish handshaking and add the peer to the list
                    PeerProtocol.SendHandshake(netStream, torrent.Metainfo.InfoDigest);
                    PeerProtocol.SendPeerId(netStream, mLocalPeerId);

                    if (!PeerProtocol.ReceivePeerId(netStream, ref peerId))
                    {                     // NAT check, discard
                        socket.Close();
                    }
                    else
                    {
                        if (!peerId.Equals(mLocalPeerId))                             // make sure we aren't connecting to ourselves
                        {
                            Net.IPEndPoint  endPoint        = (Net.IPEndPoint)socket.RemoteEndPoint;
                            PeerInformation peerInformation = new PeerInformation(endPoint.Address.ToString(), endPoint.Port, peerId);

                            // add the peer to the torrent
                            torrent.AddPeer(socket, netStream, peerInformation);
                        }
                        else
                        {
                            socket.Close();
                        }
                    }
                }
                else
                {
                    socket.Close();
                }
            }
            catch (System.Exception e)
            {
                Config.LogException(e);
                socket.Close();
            }

            this.mListener.BeginAccept(new System.AsyncCallback(OnAccept), null);
        }
예제 #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 void OnAccept(System.IAsyncResult result)
		{
			Sockets.Socket socket;

			try
			{
				// Accept connections from other peers, find the appropriate torrent and add the peer to it
				socket = this.mListener.EndAccept(result);
			}
			catch (System.Exception)
			{
				if (this.mListener != null)
					this.mListener.Close();
				this.mListener = null;
				return;
			}

			try
			{
				ByteField20 infoDigest = new ByteField20(), peerId = new ByteField20();
				Sockets.NetworkStream netStream = new Sockets.NetworkStream(socket, true);
				
				PeerProtocol.ReceiveHandshake(netStream, ref infoDigest);

				Torrent torrent = this.FindTorrent(infoDigest);

				if (torrent != null)
				{
					// found it, finish handshaking and add the peer to the list
					PeerProtocol.SendHandshake(netStream, torrent.Metainfo.InfoDigest);
					PeerProtocol.SendPeerId(netStream, mLocalPeerId );

					if ( !PeerProtocol.ReceivePeerId( netStream, ref peerId ))
					{ // NAT check, discard
						socket.Close();
					}
					else
					{
						if ( !peerId.Equals( mLocalPeerId ) ) // make sure we aren't connecting to ourselves
						{
							Net.IPEndPoint endPoint = (Net.IPEndPoint)socket.RemoteEndPoint;
							PeerInformation peerInformation = new PeerInformation( endPoint.Address.ToString(), endPoint.Port, peerId );

							// add the peer to the torrent
							torrent.AddPeer( socket, netStream, peerInformation );
						}
						else
							socket.Close();
					}
				}
				else
					socket.Close();
			}
			catch (System.Exception e)
			{
				Config.LogException( e );
				socket.Close();
			}

			this.mListener.BeginAccept(new System.AsyncCallback(OnAccept), null);
		}
예제 #5
0
		/// <summary>
		/// Helper thread method to start the connection to peers
		/// </summary>
		/// <param name="state"></param>
		private void StartPeerConnectionThread(System.IAsyncResult result)
		{
			object[] objs = (object[])result.AsyncState;
			Sockets.Socket socket = (Sockets.Socket)objs[0];
			PeerInformation peerinfo = (PeerInformation)objs[1];
			ByteField20 infoDigest = new ByteField20(), peerId = new ByteField20();
			Sockets.NetworkStream netStream;

			try
			{
				socket.EndConnect(result);

				netStream = new Sockets.NetworkStream(socket, true);

				// send handshake info
				PeerProtocol.SendHandshake(netStream, this.infofile.InfoDigest);
				PeerProtocol.ReceiveHandshake(netStream, ref infoDigest);
				PeerProtocol.SendPeerId(netStream, this.mSession.LocalPeerID );

				if (!PeerProtocol.ReceivePeerId(netStream, ref peerId))
				{ // NAT check
					socket.Close();
					return;
				}

				// check info digest matches and we are not attempting to connect to ourself
				if ( infoDigest.Equals( this.infofile.InfoDigest ) && !peerId.Equals( this.mSession.LocalPeerID ) )
				{
					peerinfo.ID = peerId;
					this.AddPeer(socket, netStream, peerinfo);
				}
				else // info digest doesn't match, close the connection
					socket.Close();
			}
			catch (System.Exception e)
			{
				Config.LogException(e);
				// die if the connection failed
				if (socket != null)
					socket.Close();
				return;
			}
		}
예제 #6
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);
		}