/// <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; } }
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); }
/// <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); } }
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); }
/// <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; } }
/// <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); }