protected virtual void HandlePieceMessage(PeerId id, PieceMessage message, PeerMessage.Releaser releaser) { id.PiecesReceived++; if (Manager.PieceManager.PieceDataReceived(id, message, out bool _, out IList <IPeer> peersInvolved)) { WritePieceAsync(message, releaser, peersInvolved); }
public void PieceDecoding() { PieceMessage message = new PieceMessage(15, 10, Piece.BlockSize); message.Data = new byte[Piece.BlockSize]; EncodeDecode(message); }
private void CompleteSendOrReceiveFirst(byte[] buffer, IAsyncResult receiveResult, IAsyncResult sendResult) { int received = 0; Wait(receiveResult.AsyncWaitHandle); while ((received = connection.EndReceive(receiveResult)) != 0) { if (received != 4) { throw new Exception("Should be 4 bytes"); } int size = IPAddress.NetworkToHostOrder(BitConverter.ToInt32(buffer, 0)); received = 0; while (received != size) { IAsyncResult r = connection.BeginReceive(buffer, received + 4, size - received, null, null); Wait(r.AsyncWaitHandle); received += connection.EndReceive(r); } PieceMessage m = (PieceMessage)PeerMessage.DecodeMessage(buffer, 0, size + 4, rig.Manager); RequestMessage request = (RequestMessage)requests.Messages[0]; Assert.AreEqual(request.PieceIndex, m.PieceIndex, "#1"); Assert.AreEqual(request.RequestLength, m.RequestLength, "#1"); Assert.AreEqual(request.StartOffset, m.StartOffset, "#1"); for (int i = 0; i < request.RequestLength; i++) { if (buffer[i + 13] != (byte)(m.PieceIndex * rig.Torrent.PieceLength + m.StartOffset + i)) { throw new Exception("Corrupted data received"); } } requests.Messages.RemoveAt(0); if (requests.Messages.Count == 0) { //receiveResult = connection.BeginReceive(buffer, 0, 4, null, null); Wait(sendResult.AsyncWaitHandle); Assert.AreEqual(connection.EndSend(sendResult), amountSent); break; } receiveResult = connection.BeginReceive(buffer, 0, 4, null, null); } var baseUri = new Uri(listenerURL); baseUri = new Uri(baseUri, rig.Manager.Torrent.Name + "/"); if (rig.Manager.Torrent.Files.Length <= 1) { return; } Assert.AreEqual(new Uri(baseUri, rig.Manager.Torrent.Files[0].Path), _requestedUrl[0]); Assert.AreEqual(new Uri(baseUri, rig.Manager.Torrent.Files[1].Path), _requestedUrl[1]); }
public HttpRequestData(BlockInfo blockInfo) { BlockInfo = blockInfo; var m = new PieceMessage(BlockInfo.PieceIndex, BlockInfo.StartOffset, BlockInfo.RequestLength); TotalToReceive = m.ByteLength; }
public HttpRequestData(RequestMessage request) { Request = request; var m = new PieceMessage(request.PieceIndex, request.StartOffset, request.RequestLength); TotalToReceive = m.ByteLength; }
protected virtual void HandleRequestMessage (PeerId id, RequestMessage message) { // If we are not on the last piece and the user requested a stupidly big/small amount of data // we will close the connection if (Manager.Torrent.Pieces.Count != (message.PieceIndex + 1)) if (message.RequestLength > RequestMessage.MaxSize || message.RequestLength < RequestMessage.MinSize) throw new MessageException ( $"Illegal piece request received. Peer requested {message.RequestLength} byte"); var m = new PieceMessage (message.PieceIndex, message.StartOffset, message.RequestLength); // If we're not choking the peer, enqueue the message right away if (!id.AmChoking) { id.IsRequestingPiecesCount++; id.Enqueue (m); } // If the peer supports fast peer and the requested piece is one of the allowed pieces, enqueue it // otherwise send back a reject request message else if (id.SupportsFastPeer && ClientEngine.SupportsFastPeer) { if (id.AmAllowedFastPieces.Contains (message.PieceIndex)) { id.IsRequestingPiecesCount++; id.Enqueue (m); } else id.Enqueue (new RejectRequestMessage (m)); } }
public async Task CountPieceMessageBlockLengthAsData() { var blockSize = Constants.BlockSize - 1234; var msg = new PieceMessage(0, 0, blockSize); msg.SetData(new MemoryPool().Rent(blockSize)); var protocolSize = msg.ByteLength - blockSize; await Task.WhenAll( PeerIO.SendMessageAsync (pair.Incoming, PlainTextEncryption.Instance, msg, null, pair.Incoming.Monitor, pair.Incoming.ManagerMonitor).AsTask(), PeerIO.ReceiveMessageAsync (pair.Outgoing, PlainTextEncryption.Instance, null, pair.Outgoing.Monitor, pair.Outgoing.ManagerMonitor, null).AsTask() ); // incoming connection sends 1 message so should receive nothing. Assert.AreEqual(0, pair.Incoming.Monitor.DataBytesDownloaded); Assert.AreEqual(0, pair.Incoming.ManagerMonitor.DataBytesDownloaded); Assert.AreEqual(0, pair.Incoming.Monitor.ProtocolBytesDownloaded); Assert.AreEqual(0, pair.Incoming.ManagerMonitor.ProtocolBytesDownloaded); Assert.AreEqual(blockSize, pair.Incoming.Monitor.DataBytesUploaded); Assert.AreEqual(blockSize, pair.Incoming.ManagerMonitor.DataBytesUploaded); Assert.AreEqual(protocolSize, pair.Incoming.Monitor.ProtocolBytesUploaded); Assert.AreEqual(protocolSize, pair.Incoming.ManagerMonitor.ProtocolBytesUploaded); // outgoing connection receives 1 message, so should send nothing. Assert.AreEqual(0, pair.Outgoing.Monitor.DataBytesUploaded); Assert.AreEqual(0, pair.Outgoing.ManagerMonitor.DataBytesUploaded); Assert.AreEqual(0, pair.Outgoing.Monitor.ProtocolBytesUploaded); Assert.AreEqual(0, pair.Outgoing.ManagerMonitor.ProtocolBytesUploaded); Assert.AreEqual(blockSize, pair.Outgoing.Monitor.DataBytesDownloaded); Assert.AreEqual(blockSize, pair.Outgoing.ManagerMonitor.DataBytesDownloaded); Assert.AreEqual(protocolSize, pair.Outgoing.Monitor.ProtocolBytesDownloaded); Assert.AreEqual(protocolSize, pair.Outgoing.ManagerMonitor.ProtocolBytesDownloaded); }
protected virtual void HandleCancelMessage(PeerId id, CancelMessage message) { PeerMessage msg; for (int i = 0; i < id.QueueLength; i++) { msg = id.Dequeue(); if (!(msg is PieceMessage)) { id.Enqueue(msg); continue; } PieceMessage piece = msg as PieceMessage; if (!(piece.PieceIndex == message.PieceIndex && piece.StartOffset == message.StartOffset && piece.RequestLength == message.RequestLength)) { id.Enqueue(msg); } else { id.IsRequestingPiecesCount--; } } for (int i = 0; i < id.PieceReads.Count; i++) { if (id.PieceReads[i].PieceIndex == message.PieceIndex && id.PieceReads[i].StartOffset == message.StartOffset && id.PieceReads[i].RequestLength == message.RequestLength) { id.IsRequestingPiecesCount--; id.PieceReads.RemoveAt(i); break; } } }
/// <summary> /// Processes the received message. /// </summary> /// <param name="message">The message.</param> private void ProcessRecievedMessage(PieceMessage message) { message.CannotBeNull(); if (this.HandshakeState == HandshakeState.SendAndReceived) { if (message.PieceIndex >= 0 && message.PieceIndex < this.pieceManager.PieceCount && message.BlockOffset >= 0 && message.BlockOffset < this.pieceManager.PieceLength && message.BlockOffset % this.pieceManager.BlockLength == 0 && message.Data.Length == this.pieceManager.GetPieceLength(message.PieceIndex)) { this.EnqueueDownloadMessage(message); } else { this.OnCommunicationErrorOccurred(this, new PeerCommunicationErrorEventArgs("Invalid piece message.", false)); } } else { this.OnCommunicationErrorOccurred(this, new PeerCommunicationErrorEventArgs("Invalid message sequence.", true)); } }
/// <param name="id">The peer whose message queue you want to start processing</param> internal void ProcessQueue(PeerId id) { if (id.QueueLength == 0) { id.ProcessingQueue = false; return; } PeerMessage msg = id.Dequeue(); if (msg is PieceMessage) { using (ManualResetEvent handle = new ManualResetEvent(false)) { PieceMessage pm = (PieceMessage)msg; pm.Data = BufferManager.EmptyBuffer; ClientEngine.BufferManager.GetBuffer(ref pm.Data, pm.ByteLength); engine.DiskManager.QueueRead(id.TorrentManager, pm.StartOffset + ((long)pm.PieceIndex * id.TorrentManager.Torrent.PieceLength), pm.Data, pm.RequestLength, delegate { handle.Set(); }); handle.WaitOne(); id.PiecesSent++; } } try { SendMessage(id, msg, this.messageSentCallback); } catch (Exception e) { CleanupSocket(id, "Exception calling SendMessage: " + e.Message); } }
public void PieceEncoding() { PieceMessage message = new PieceMessage(15, 10, Piece.BlockSize); message.Data = new byte[Piece.BlockSize]; message.Encode(buffer, offset); }
protected virtual void HandlePieceMessage(PeerId id, PieceMessage message) { id.PiecesReceived++; manager.PieceManager.PieceDataReceived(id, message); // Keep adding new piece requests to this peers queue until we reach the max pieces we're allowed queue manager.PieceManager.AddPieceRequests(id); }
public void PieceEncoding() { PieceMessage message = new PieceMessage(15, 10, Piece.BlockSize) { DataReleaser = new ByteBufferPool.Releaser(null, new ByteBuffer(Piece.BlockSize)) }; message.Encode(buffer, offset); }
public void PieceEncoding() { var message = new PieceMessage(15, 10, Piece.BlockSize) { Data = new byte[Piece.BlockSize] }; message.Encode(_buffer, Offset); }
public void PieceDecoding() { PieceMessage message = new PieceMessage(15, 10, Piece.BlockSize) { DataReleaser = new ByteBufferPool.Releaser(null, new ByteBuffer(Piece.BlockSize)) }; EncodeDecode(message); }
public void PieceDecoding() { var message = new PieceMessage(15, 10, Piece.BlockSize) { Data = new byte[Piece.BlockSize] }; EncodeDecode(message); }
protected virtual void HandlePieceMessage (PeerId id, PieceMessage message) { id.PiecesReceived++; Piece piece = Manager.PieceManager.PieceDataReceived (id, message); if (piece != null) WritePieceAsync (message, piece); else ClientEngine.BufferPool.Return (message.Data); // Keep adding new piece requests to this peers queue until we reach the max pieces we're allowed queue Manager.PieceManager.AddPieceRequests (id); }
private async Task CompleteSendOrReceiveFirst(SocketMemory buffer) { var allRequests = new List <RequestMessage> (); var requestsBuffer = requests.Encode().AsMemory(); while (requestsBuffer.Length > 0) { var message = (RequestMessage)PeerMessage.DecodeMessage(requestsBuffer.Span, null).message; allRequests.Add(message); requestsBuffer = requestsBuffer.Slice(message.ByteLength); } while (allRequests.Count > 0) { int size = Message.ReadInt(buffer.Span); await NetworkIO.ReceiveAsync(connection, buffer.Slice(4, size), null, null, null); PieceMessage m = (PieceMessage)PeerMessage.DecodeMessage(buffer.AsSpan(0, size + 4), rig.Manager).message; var request = allRequests[0]; Assert.AreEqual(request.PieceIndex, m.PieceIndex, "#1"); Assert.AreEqual(request.RequestLength, m.RequestLength, "#1"); Assert.AreEqual(request.StartOffset, m.StartOffset, "#1"); for (int i = 0; i < request.RequestLength; i++) { if (buffer.Span[i + 13] != (byte)(m.PieceIndex * rig.Torrent.PieceLength + m.StartOffset + i)) { throw new Exception("Corrupted data received"); } } allRequests.RemoveAt(0); if (allRequests.Count == 0) { break; } else { await NetworkIO.ReceiveAsync(connection, buffer.Slice(0, 4), null, null, null);; } } Uri baseUri = new Uri(ListenerURL); baseUri = new Uri(baseUri, $"{rig.Manager.Torrent.Name}/"); if (rig.Manager.Torrent.Files.Count > 1) { Assert.AreEqual(new Uri(baseUri, rig.Manager.Torrent.Files[0].Path), requestedUrl[0]); Assert.AreEqual(new Uri(baseUri, rig.Manager.Torrent.Files[1].Path), requestedUrl[1]); } }
async void WritePieceAsync (PieceMessage message, Piece piece) { long offset = (long) message.PieceIndex * Manager.Torrent.PieceLength + message.StartOffset; try { await DiskManager.WriteAsync (Manager.Torrent, offset, message.Data, message.RequestLength); if (Cancellation.IsCancellationRequested) return; } catch (Exception ex) { Manager.TrySetError (Reason.WriteFailure, ex); return; } finally { ClientEngine.BufferPool.Return (message.Data); } piece.TotalWritten++; // If we haven't received all the pieces to disk, there's no point in hash checking if (!piece.AllBlocksWritten) return; // Hashcheck the piece as we now have all the blocks. byte[] hash; try { hash = await DiskManager.GetHashAsync (Manager.Torrent, piece.Index); if (Cancellation.IsCancellationRequested) return; } catch (Exception ex) { Manager.TrySetError (Reason.ReadFailure, ex); return; } bool result = hash != null && Manager.Torrent.Pieces.IsValid (hash, piece.Index); Manager.OnPieceHashed (piece.Index, result, 1, 1); Manager.PieceManager.PendingHashCheckPieces[piece.Index] = false; if (!result) Manager.HashFails++; for (int i = 0; i < piece.Blocks.Length; i++) if (piece.Blocks[i].RequestedOff != null) peers.Add ((PeerId) piece.Blocks[i].RequestedOff); foreach (PeerId peer in peers) { peer.Peer.HashedPiece (result); if (peer.Peer.TotalHashFails == 5) ConnectionManager.CleanupSocket (Manager, peer); } peers.Clear (); // If the piece was successfully hashed, enqueue a new "have" message to be sent out if (result) Manager.finishedPieces.Enqueue (new HaveMessage (piece.Index)); }
internal Piece PieceDataReceived(PeerId id, PieceMessage message) { if (Picker.ValidatePiece(id, message.PieceIndex, message.StartOffset, message.RequestLength, out Piece piece)) { id.LastBlockReceived.Restart(); if (piece.AllBlocksReceived) { PendingHashCheckPieces[message.PieceIndex] = true; } return(piece); } return(null); }
private void WriteBlock(PieceMessage piece) { try { var block = new Block(piece.Data, piece.Index, piece.Offset, piece.Data.Length); BlockManager.AddBlock(block, BlockWritten, block); Interlocked.Add(ref pendingWrites, piece.Data.Length); } catch (Exception e) { HandleException(e); } }
async void WritePieceAsync(PeerId id, PieceMessage message, Piece piece) { long offset = (long)message.PieceIndex * id.TorrentManager.Torrent.PieceLength + message.StartOffset; await id.TorrentManager.Engine.DiskManager.WriteAsync(Manager, offset, message.Data, message.RequestLength); piece.TotalWritten++; ClientEngine.BufferManager.FreeBuffer(message.Data); // If we haven't received all the pieces to disk, there's no point in hash checking if (!piece.AllBlocksWritten) { return; } // Hashcheck the piece as we now have all the blocks. var hash = await id.Engine.DiskManager.GetHashAsync(id.TorrentManager, piece.Index); bool result = hash != null && id.TorrentManager.Torrent.Pieces.IsValid(hash, piece.Index); Manager.OnPieceHashed(piece.Index, result); Manager.PieceManager.UnhashedPieces[piece.Index] = false; if (!result) { Manager.HashFails++; } for (int i = 0; i < piece.Blocks.Length; i++) { if (piece.Blocks[i].RequestedOff != null) { peers.Add(piece.Blocks[i].RequestedOff); } } foreach (PeerId peer in peers) { peer.Peer.HashedPiece(result); if (peer.Peer.TotalHashFails == 5) { Manager.Engine.ConnectionManager.CleanupSocket(peer, "Too many hash fails"); } } peers.Clear(); // If the piece was successfully hashed, enqueue a new "have" message to be sent out if (result) { Manager.finishedPieces.Enqueue(new HaveMessage(piece.Index)); } }
public void IgnoreNullMonitors() { var blockSize = Constants.BlockSize - 1234; var msg = new PieceMessage(0, 0, blockSize); msg.SetData(new MemoryPool().Rent(blockSize)); Assert.DoesNotThrowAsync(() => { return(Task.WhenAll( PeerIO.SendMessageAsync(pair.Incoming, PlainTextEncryption.Instance, msg).AsTask(), PeerIO.ReceiveMessageAsync(pair.Outgoing, PlainTextEncryption.Instance).AsTask() )); }); }
protected override void HandlePiece(PieceMessage piece, PeerState peer) { var blockInfo = new BlockInfo(piece.Index, piece.Offset, piece.Data.Length); //съобщаваме на BlockStrategistът, че сме получили блок, а той ни казва дали ни е нужен if (BlockStrategist.Received(blockInfo)) { //ако блока е нужен, записваме го WriteBlock(piece); } //понижаване на брояча за блоковете в изчакване peer.PendingBlocks--; //изпращане на нова заявка за блок към пиъра SendBlockRequests(peer); }
public void IgnoreNullMonitors() { var blockSize = Piece.BlockSize - 1234; var msg = new PieceMessage(0, 0, blockSize) { DataReleaser = new ByteBufferPool.Releaser(null, new ByteBuffer(blockSize)) }; Assert.DoesNotThrowAsync(() => { return(Task.WhenAll( PeerIO.SendMessageAsync(pair.Incoming, PlainTextEncryption.Instance, msg).AsTask(), PeerIO.ReceiveMessageAsync(pair.Outgoing, PlainTextEncryption.Instance).AsTask() )); }); }
protected virtual void HandlePieceMessage(PeerId id, PieceMessage message) { id.PiecesReceived++; var piece = Manager.PieceManager.PieceDataReceived(id, message); if (piece != null) { WritePieceAsync(id, message, piece); } else { ClientEngine.BufferManager.FreeBuffer(ref message.Data); } // Keep adding new piece requests to this peers queue until we reach the max pieces we're allowed queue Manager.PieceManager.AddPieceRequests(id); }
protected virtual void HandlePieceMessage(PeerId id, PieceMessage message) { id.PiecesReceived++; Piece piece = Manager.PieceManager.PieceDataReceived(id, message); if (piece != null) { WritePieceAsync(message, piece); } else { message.DataReleaser.Dispose(); } // Keep adding new piece requests to this peers queue until we reach the max pieces we're allowed queue Manager.PieceManager.AddPieceRequests(id); }
private async Task CompleteSendOrReceiveFirst(byte[] buffer) { var allRequests = requests.ToRequestMessages().ToList(); while (allRequests.Count > 0) { int size = IPAddress.NetworkToHostOrder(BitConverter.ToInt32(buffer, 0)); await NetworkIO.ReceiveAsync(connection, buffer, 4, size, null, null, null); PieceMessage m = (PieceMessage)PeerMessage.DecodeMessage(buffer, 0, size + 4, rig.Manager.Torrent); var request = allRequests[0]; Assert.AreEqual(request.PieceIndex, m.PieceIndex, "#1"); Assert.AreEqual(request.RequestLength, m.RequestLength, "#1"); Assert.AreEqual(request.StartOffset, m.StartOffset, "#1"); for (int i = 0; i < request.RequestLength; i++) { if (buffer[i + 13] != (byte)(m.PieceIndex * rig.Torrent.PieceLength + m.StartOffset + i)) { throw new Exception("Corrupted data received"); } } allRequests.RemoveAt(0); if (allRequests.Count == 0) { break; } else { await NetworkIO.ReceiveAsync(connection, buffer, 0, 4, null, null, null); } } Uri baseUri = new Uri(ListenerURL); baseUri = new Uri(baseUri, $"{rig.Manager.Torrent.Name}/"); if (rig.Manager.Torrent.Files.Length > 1) { Assert.AreEqual(new Uri(baseUri, rig.Manager.Torrent.Files[0].Path), requestedUrl[0]); Assert.AreEqual(new Uri(baseUri, rig.Manager.Torrent.Files[1].Path), requestedUrl[1]); } }
internal bool PieceDataReceived(PeerId id, PieceMessage message, out bool pieceComplete, out IList <IPeer> peersInvolved) { if (Initialised && Requester.Picker.ValidatePiece(id, new BlockInfo(message.PieceIndex, message.StartOffset, message.RequestLength), out pieceComplete, out peersInvolved)) { id.LastBlockReceived.Restart(); if (pieceComplete) { PendingHashCheckPieces[message.PieceIndex] = true; } return(true); } else { pieceComplete = false; peersInvolved = null; return(false); } }
public Piece PieceDataReceived(PeerId id, PieceMessage message) { Piece piece; if (Picker.ValidatePiece(id, message.PieceIndex, message.StartOffset, message.RequestLength, out piece)) { id.LastBlockReceived.Restart(); var block = piece.Blocks [message.StartOffset / Piece.BlockSize]; RaiseBlockReceived(new BlockEventArgs(id.TorrentManager, block, piece, id)); if (piece.AllBlocksReceived) { UnhashedPieces[message.PieceIndex] = true; } return(piece); } return(null); }
protected virtual void HandlePieceMessage(PeerId id, PieceMessage message) { id.PiecesReceived++; _manager.PieceManager.PieceDataReceived(id, message); // Keep adding new piece requests to this peers queue until we reach the max pieces we're allowed queue _manager.PieceManager.AddPieceRequests(id); }
protected virtual void HandleRequestMessage(PeerId id, RequestMessage message) { // If we are not on the last piece and the user requested a stupidly big/small amount of data // we will close the connection if (_manager.Torrent.Pieces.Count != (message.PieceIndex + 1)) if (message.RequestLength > RequestMessage.MaxSize || message.RequestLength < RequestMessage.MinSize) throw new MessageException("Illegal piece request received. Peer requested " + message.RequestLength.ToString() + " byte"); var m = new PieceMessage(message.PieceIndex, message.StartOffset, message.RequestLength); // If we're not choking the peer, enqueue the message right away if (!id.AmChoking) { id.IsRequestingPiecesCount++; id.PieceReads.Add(m); id.TryProcessAsyncReads(); } // If the peer supports fast peer and the requested piece is one of the allowed pieces, enqueue it // otherwise send back a reject request message else if (id.SupportsFastPeer && ClientEngine.SupportsFastPeer) { if (id.AmAllowedFastPieces.Contains(message.PieceIndex)) { id.IsRequestingPiecesCount++; id.PieceReads.Add(m); id.TryProcessAsyncReads(); } else id.Enqueue(new RejectRequestMessage(m)); } }
public RejectRequestMessage(PieceMessage message) : this(message.PieceIndex, message.StartOffset, message.RequestLength) { }