public bool BeginConnection() { Client = new TcpClient(); Client.ReceiveTimeout = 1000; var result = Client.BeginConnect(this.IP, this.Port, null, null); Console.WriteLine("Connecting to: {0}:{1}", this.IP, this.Port); var success = result.AsyncWaitHandle.WaitOne(TimeSpan.FromSeconds(5)); if (!success || !Client.Connected) { return(false); } Stream = Client.GetStream(); Stream.ReadTimeout = 6000; byte[] handshake = PacketGenerator.Handshake("BitTorrent protocol", Infohash, PeerClientID); Stream.Write(handshake, 0, handshake.Length); Stream.Flush(); #if DEBUG Console.WriteLine("Sent packet!"); #endif byte[] realRead = Read(); if (realRead.Length < 49) { #if DEBUG Console.WriteLine("Invalid handshake packet! Exiting!"); #endif Stream.Close(); Client.Close(); return(false); } #if DEBUG Console.WriteLine("Received: {0} bytes", realRead.Length); #endif PacketGenerator gs = new PacketGenerator(realRead); if (!Handshake(gs)) { #if DEBUG Console.WriteLine("Handshake failed!"); #endif Stream.Close(); Client.Close(); return(false); } Console.WriteLine("Connected!"); State = PeerState.CHOKED; ChokeTimer.Reset(); _ReadThread = new Thread(ReadThread); _ReadThread.Start(); TimeManager resentTimer = new TimeManager(); while (ThreadWorking) { if (AliveTimer.GetElapsedSeconds() > 20.0 && resentTimer.GetElapsedSeconds() > 10.0) { resentTimer.Reset(); if (LastPacketSent == null) { Send(PacketGenerator.KeepAlive()); } else { Send(LastPacketSent); } } if (AliveTimer.GetElapsedSeconds() > 60.0) { ThreadWorking = false; } Thread.Sleep(100); } ThreadWorking = false; return(true); }
public void ReadThread() { Stream.ReadTimeout = 40000;// 40s timeout try { while (ThreadWorking) { Send(PacketGenerator.Interested()); Send(PacketGenerator.Unchoke()); if (State == PeerState.CHOKED) { if (ChokeTimer.GetElapsedSeconds() >= 30.0) { ThreadWorking = false; break; } } byte packetID = 0; byte[] received = ReadPacket(ref packetID); if (packetID <= 9) { AliveTimer.Reset(); } #if DEBUG Console.WriteLine("Received packet: {0}", packetID == 0xF0 ? "Keep-Alive" : Convert.ToString(packetID)); #endif switch (packetID) { case 0xF0: //KEEP_ALIVE //AliveTimer.Reset(); if (State == PeerState.READY) { if (RequestForNewPiece() == -1) { //all pieces downloaded or failed State = PeerState.SHAKING; ThreadWorking = false; } } //SendPacket(null, 0); break; case 0: //CHOKE ChokeTimer.Reset(); State = PeerState.CHOKED; break; case 1: //UNCHOKE if (State == PeerState.CHOKED) { // Send(PacketGenerator.Interested()); //Console.WriteLine("Sent Interested Packet!"); if (RequestForNewPiece() == -1) { //all pieces downloaded or failed State = PeerState.SHAKING; ThreadWorking = false; } Send(PacketGenerator.Unchoke()); } if (State == PeerState.CHOKED) { State = PeerState.READY; } break; case 2: //INTERESTED State = PeerState.READY; if (RequestForNewPiece() == -1) { //all pieces downloaded or failed State = PeerState.SHAKING; ThreadWorking = false; } break; case 3: //NOTINTERESTED ThreadWorking = false; #if DEBUG Console.WriteLine("Killing thread.. Not interested."); #endif break; case 4: //HAVE Have(received); // OK break; case 5: //BITFIELD BitField(received); break; case 6: //REQUEST FetchAndSendPiece(received); break; case 7: //PIECE State = PeerState.READY; if (SavePieceAndRequestForNewOne(received) == -1) { //all pieces downloaded or failed State = PeerState.SHAKING; ThreadWorking = false; } break; case 8: //CANCEL //No need break; case 9: //PORT //Unused break; } } } catch (Exception e) { ThreadWorking = false; #if DEBUG Console.WriteLine("ThreadException: {0}", e.Message); #endif } }
public bool Start() { BitFile fs = new BitFile(this.TorrentFile.File.FileName, this.TorrentFile.File.Md5Sum, this.TorrentFile.File.FileSize, (long)Math.Ceiling((double)this.TorrentFile.File.FileSize / (double)this.TorrentFile.PieceSize), this.TorrentFile.PieceSize); loopStart: if (fs.AlmostFinished()) { Console.WriteLine("Flushing buffers!"); while (!fs.Finished()) { Thread.Sleep(5); } } if (fs.Finished()) { return(true); } Console.WriteLine("Announcing..."); if (!this.TrackerManager.Announce()) { return(false); } Timer.Reset(); for (int i = 0; i < TrackerManager.GetPeers().Count; i++) { var peerInfo = TrackerManager.GetPeers()[i]; Peer pr = new Peer(peerInfo.IP, peerInfo.Port, this.TorrentFile.GetInfoHash(), TrackerManager.GetPeerID(), fs); try { if (!pr.BeginConnection()) { continue; } } catch (Exception e) { #if DEBUG Console.WriteLine("Exception: {0}", e.Message); #endif if (pr._ReadThread != null) { pr._ReadThread.Abort(); } continue; } if (fs.AlmostFinished()) { Console.WriteLine("File successfully downloaded!"); goto loopStart; } if (Timer.GetElapsedSeconds() >= 60.0 * 5) { goto loopStart; } } goto loopStart; }