public int RequestForNewPiece() { int piece = 0, offset = 0, length = 0; if (!CurrentFile.GetNextMissingPiece(ref piece, ref offset, ref length)) { return(-1); } if (!DifferenceBitField.GetPiece(piece)) { #if DEBUG Console.WriteLine("Cutting connection.. Peer does not have the piece"); #endif return(-1); //does not have the piece } #if DEBUG Console.WriteLine("Requesting for piece: {0}", piece); #endif byte[] pieceRequest = PacketGenerator.Request(piece, offset, length); Send(pieceRequest); State = PeerState.DOWNLOADING; return(piece); }
public static byte[] Unchoke() { PacketGenerator rs = new PacketGenerator(); rs.WriteInt(1); //Length rs.WriteByte(1); //ID return(rs.GetByteArray()); }
public static byte[] NotInterested() { PacketGenerator rs = new PacketGenerator(); rs.WriteInt(1); //Length rs.WriteByte(3); //ID return(rs.GetByteArray()); }
public void Have(byte[] data) { PacketGenerator gs = new PacketGenerator(data); int piece = gs.ReadInt(); #if DEBUG Console.WriteLine("Successfully uploaded piece {0}", piece); #endif }
public static byte[] BitField(byte[] bitfield) { PacketGenerator rs = new PacketGenerator(); rs.WriteInt(1 + bitfield.Length); //Length rs.WriteByte(5); //ID rs.WriteByteArray(bitfield); //Payload: Bitfield return(rs.GetByteArray()); }
public static byte[] Have(int piece) { PacketGenerator rs = new PacketGenerator(); rs.WriteInt(5); //Length rs.WriteByte(4); //ID rs.WriteInt(piece); //Payload: Piece ID return(rs.GetByteArray()); }
public static byte[] Port(short listen_port) //Used for DHT, currently unimplemented { PacketGenerator rs = new PacketGenerator(); rs.WriteInt(3); //Length rs.WriteByte(9); //ID rs.WriteShort(listen_port); return(rs.GetByteArray()); }
public static byte[] Cancel(int pieceid, int piece_begin_offset, int piecelength) //Same parameters as 'Request' message { PacketGenerator rs = new PacketGenerator(); rs.WriteInt(13); //Length rs.WriteByte(8); //ID rs.WriteInt(pieceid); //Payload: Piece ID [index] rs.WriteInt(piece_begin_offset); //Payload: Byte Offset [begin] rs.WriteInt(piecelength); //Payload: Piece Read Length [length] return(rs.GetByteArray()); }
public static byte[] Piece(int pieceid, int piece_begin_offset, byte[] piece_part) //WARNING: USE REQUESTED AMOUNT OF BYTES (MAX 16KB) AT A TIME, SEND IN MULTIPLE REQUESTS { PacketGenerator rs = new PacketGenerator(); rs.WriteInt(9 + piece_part.Length); //Length rs.WriteByte(7); //ID rs.WriteInt(pieceid); //Payload: Piece ID [index] rs.WriteInt(piece_begin_offset); //Payload: Byte Offset [begin] rs.WriteByteArray(piece_part); //Payload: Piece Block [block] return(rs.GetByteArray()); }
public static byte[] Request(int pieceid, int piece_begin_offset, int piecelength) //WARNING: USE 16 KILOBYTES (2^14) AT A TIME, DOWNLOAD IN MULTIPLE REQUESTS { PacketGenerator rs = new PacketGenerator(); rs.WriteInt(13); //Length rs.WriteByte(6); //ID rs.WriteInt(pieceid); //Payload: Piece ID [index] rs.WriteInt(piece_begin_offset); //Payload: Byte Offset [begin] rs.WriteInt(piecelength); //Payload: Piece Read Length [length] return(rs.GetByteArray()); }
public static byte[] Handshake(string clientName, byte[] info_hash, string peer_id) { PacketGenerator rs = new PacketGenerator(); byte[] reservedBytes = { 0, 0, 0, 0, 0, 0, 0, 0 }; rs.WriteByte(Convert.ToByte(clientName.Length)); rs.WriteString(clientName); rs.WriteByteArray(reservedBytes); rs.WriteByteArray(info_hash); rs.WriteString(peer_id); return(rs.GetByteArray()); }
public void FetchAndSendPiece(byte[] packet) { PacketGenerator gs = new PacketGenerator(packet); int pieceRequested = gs.ReadInt(); int pieceOffset = gs.ReadInt(); int length = gs.ReadInt(); byte[] fileData = new byte[1]; if (CurrentFile.ReadPiece(pieceRequested, ref fileData, pieceOffset, length)) { #if DEBUG Console.WriteLine("Sending piece: {0}", pieceRequested); #endif byte[] send = PacketGenerator.Piece(pieceRequested, pieceOffset, fileData); Send(send); } }
public int SavePieceAndRequestForNewOne(byte[] packet) { PacketGenerator gs = new PacketGenerator(packet); int piece = gs.ReadInt(); int pieceOffset = gs.ReadInt(); byte[] data = gs.ReadLeftoverByteArray(); CurrentFile.WritePiece(piece, pieceOffset, data); Console.WriteLine("Received piece: {0} {1:0.000}%", piece, ((float)CurrentFile.GetDownloadedSize() / (float)CurrentFile.GetSize()) * 100.0); if (data.Length < 1024 * 16) { byte[] have = PacketGenerator.Have(piece); Send(have); // Console.WriteLine("Successfully downloaded piece: {0}", piece); } return(RequestForNewPiece()); }
public bool Handshake(PacketGenerator gs) { int nameLength = (int)gs.ReadByte(); if (gs.GetLength() < 49 + nameLength) { #if DEBUG Console.WriteLine("Invalid namelength! Corrupted packet?"); #endif return(false); } string name = gs.ReadString(nameLength); gs.SeekIndex(8); //reservedBytes byte[] infoHash = gs.ReadByteArray(20); string peerID = gs.ReadString(20); bool HanshakeSuccess = infoHash.SequenceEqual(this.Infohash); return(HanshakeSuccess); }
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 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); }