internal async void ReceiveMessagesAsync(IConnection connection, IEncryption decryptor, RateLimiterGroup downloadLimiter, ConnectionMonitor monitor, TorrentManager torrentManager, PeerId id) { await MainLoop.SwitchToThreadpool(); ByteBufferPool.Releaser releaser = default; try { while (true) { if (id.AmRequestingPiecesCount == 0 && releaser.Buffer != null) { releaser.Dispose(); releaser = NetworkIO.BufferPool.Rent(1, out ByteBuffer _); } else if (id.AmRequestingPiecesCount > 0 && releaser.Buffer == null) { releaser.Dispose(); releaser = NetworkIO.BufferPool.Rent(Piece.BlockSize, out ByteBuffer _); } PeerMessage message = await PeerIO.ReceiveMessageAsync(connection, decryptor, downloadLimiter, monitor, torrentManager.Monitor, torrentManager, releaser.Buffer).ConfigureAwait(false); HandleReceivedMessage(id, torrentManager, message); } } catch { releaser.Dispose(); await ClientEngine.MainLoop; CleanupSocket(torrentManager, id); } }
internal async void ReceiveMessagesAsync(IPeerConnection connection, IEncryption decryptor, RateLimiterGroup downloadLimiter, ConnectionMonitor monitor, TorrentManager torrentManager, PeerId id) { await MainLoop.SwitchToThreadpool(); Memory <byte> currentBuffer = default; Memory <byte> smallBuffer = default; ByteBufferPool.Releaser smallReleaser = default; Memory <byte> largeBuffer = default; ByteBufferPool.Releaser largeReleaser = default; try { while (true) { if (id.AmRequestingPiecesCount == 0) { if (!largeBuffer.IsEmpty) { largeReleaser.Dispose(); largeReleaser = default; largeBuffer = currentBuffer = default; } if (smallBuffer.IsEmpty) { smallReleaser = NetworkIO.BufferPool.Rent(ByteBufferPool.SmallMessageBufferSize, out smallBuffer); currentBuffer = smallBuffer; } } else { if (!smallBuffer.IsEmpty) { smallReleaser.Dispose(); smallReleaser = default; smallBuffer = currentBuffer = default; } if (largeBuffer.IsEmpty) { largeReleaser = NetworkIO.BufferPool.Rent(ByteBufferPool.LargeMessageBufferSize, out largeBuffer); currentBuffer = largeBuffer; } } (PeerMessage message, PeerMessage.Releaser releaser) = await PeerIO.ReceiveMessageAsync(connection, decryptor, downloadLimiter, monitor, torrentManager.Monitor, torrentManager, currentBuffer).ConfigureAwait(false); HandleReceivedMessage(id, torrentManager, message, releaser); } } catch { await ClientEngine.MainLoop; CleanupSocket(torrentManager, id); } finally { smallReleaser.Dispose(); largeReleaser.Dispose(); } }
/// <summary> /// /// </summary> /// <param name="manager">The torrent which the peer is associated with.</param> /// <param name="id">The peer whose message queue you want to start processing</param> internal async void TryProcessQueue(TorrentManager manager, PeerId id) { if (!id.MessageQueue.BeginProcessing()) { return; } await MainLoop.SwitchToThreadpool(); ByteBufferPool.Releaser socketMemoryReleaser = default; Memory <byte> socketMemory = default; try { while (id.MessageQueue.TryDequeue(out PeerMessage? msg, out PeerMessage.Releaser msgReleaser)) { using var autorelease = msgReleaser; if (socketMemory.IsEmpty || socketMemory.Length < msg.ByteLength) { socketMemoryReleaser.Dispose(); socketMemoryReleaser = NetworkIO.BufferPool.Rent(msg.ByteLength, out socketMemory); } var buffer = socketMemory.Slice(0, msg.ByteLength); if (msg is PieceMessage pm) { pm.SetData((default, buffer.Slice(buffer.Length - pm.RequestLength)));
/// <summary> /// /// </summary> /// <param name="manager">The torrent which the peer is associated with.</param> /// <param name="id">The peer whose message queue you want to start processing</param> internal async void TryProcessQueue(TorrentManager manager, PeerId id) { if (!id.MessageQueue.BeginProcessing()) { return; } await MainLoop.SwitchToThreadpool(); ByteBufferPool.Releaser messageBuffer = default; ByteBufferPool.Releaser pieceBuffer = default; PeerMessage msg; try { while ((msg = id.MessageQueue.TryDequeue()) != null) { var msgLength = msg.ByteLength; if (msg is PieceMessage pm) { if (pieceBuffer.Buffer == null) { pieceBuffer = DiskManager.BufferPool.Rent(msgLength, out ByteBuffer _); } pm.DataReleaser = pieceBuffer; try { await DiskManager.ReadAsync(manager, pm.StartOffset + ((long)pm.PieceIndex * manager.Torrent.PieceLength), pm.Data, pm.RequestLength).ConfigureAwait(false); } catch (Exception ex) { await ClientEngine.MainLoop; manager.TrySetError(Reason.ReadFailure, ex); return; } System.Threading.Interlocked.Increment(ref id.piecesSent); } else { pieceBuffer.Dispose(); } if (messageBuffer.Buffer == null || messageBuffer.Buffer.Data.Length < msg.ByteLength) { messageBuffer.Dispose(); messageBuffer = NetworkIO.BufferPool.Rent(msgLength, out ByteBuffer _); } await PeerIO.SendMessageAsync(id.Connection, id.Encryptor, msg, manager.UploadLimiters, id.Monitor, manager.Monitor, messageBuffer.Buffer).ConfigureAwait(false); if (msg is PieceMessage) { System.Threading.Interlocked.Decrement(ref id.isRequestingPiecesCount); } id.LastMessageSent.Restart(); } } catch { await ClientEngine.MainLoop; CleanupSocket(manager, id); } finally { messageBuffer.Dispose(); pieceBuffer.Dispose(); } }