public static void EnqueueSendMessage (IConnection connection, IEncryption encryptor, PeerMessage message, IRateLimiter rateLimiter, ConnectionMonitor peerMonitor, ConnectionMonitor managerMonitor, AsyncIOCallback callback, object state) { int count = message.ByteLength; var buffer = ClientEngine.BufferManager.GetBuffer (count); message.Encode (buffer, 0); encryptor.Encrypt (buffer, 0, count); var data = sendCache.Dequeue ().Initialise (buffer, callback, state); NetworkIO.EnqueueSend (connection, buffer, 0, count, rateLimiter, peerMonitor, managerMonitor, EndSendCallback, data); }
public static void EnqueueReceiveMessage(IConnection connection, IEncryption decryptor, IRateLimiter rateLimiter, ConnectionMonitor monitor, TorrentManager manager, AsyncMessageReceivedCallback callback, object state) { // FIXME: Hardcoded number int count = 4; byte[] buffer = ClientEngine.BufferManager.GetBuffer(count); ReceiveMessageState data = receiveCache.Dequeue() .Initialise(connection, decryptor, rateLimiter, monitor, manager, buffer, callback, state); NetworkIO.EnqueueReceive(connection, buffer, 0, count, rateLimiter, monitor, data.ManagerMonitor, MessageLengthReceivedCallback, data); }
public ReceiveMessageState Initialise (IConnection connection, IEncryption decryptor, IRateLimiter limiter, ConnectionMonitor peerMonitor, TorrentManager manager, byte[] buffer, AsyncMessageReceivedCallback callback, object state) { Connection = connection; Decryptor = decryptor; Manager = manager; Buffer = buffer; PeerMonitor = peerMonitor; RateLimiter = limiter; ManagerMonitor = manager == null ? null : manager.Monitor; Callback = callback; State = state; return this; }
public AsyncIOState Initialise(IConnection connection, byte[] buffer, int offset, int count, AsyncIOCallback callback, object state, IRateLimiter limiter, ConnectionMonitor peerMonitor, ConnectionMonitor managerMonitor) { Connection = connection; Buffer = buffer; Count = count; Callback = callback; Offset = offset; ManagerMonitor = managerMonitor; PeerMonitor = peerMonitor; RateLimiter = limiter; Remaining = count; State = state; return this; }
internal PeerId(Peer peer, TorrentManager manager) { if (peer == null) throw new ArgumentNullException("peer"); SuggestedPieces = new MonoTorrentCollection<int>(); AmChoking = true; IsChoking = true; IsAllowedFastPieces = new MonoTorrentCollection<int>(); AmAllowedFastPieces = new MonoTorrentCollection<int>(); LastMessageReceived = DateTime.Now; LastMessageSent = DateTime.Now; Peer = peer; MaxPendingRequests = 2; MaxSupportedPendingRequests = 50; Monitor = new ConnectionMonitor(); sendQueue = new MonoTorrentCollection<PeerMessage>(12); ExtensionSupports = new ExtensionSupports(); TorrentManager = manager; InitializeTyrant(); }
internal async void ReceiveMessagesAsync(IPeerConnection connection, IEncryption decryptor, RateLimiterGroup downloadLimiter, ConnectionMonitor monitor, TorrentManager torrentManager, PeerId id) { await MainLoop.SwitchToThreadpool(); SocketMemory currentBuffer = default; SocketMemory smallBuffer = default; ByteBufferPool.Releaser smallReleaser = default; SocketMemory 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(); } }
internal static void EnqueueSend(IConnection connection, byte[] buffer, int offset, int count, AsyncTransfer callback, object state, RateLimiter limiter, ConnectionMonitor managerMonitor, ConnectionMonitor peerMonitor) { AsyncIO io = new AsyncIO(connection, buffer, offset, count, callback, state, limiter, managerMonitor, peerMonitor); EnqueueSend(io); }
public AsyncIO(IConnection connection, byte[] buffer, int offset, int total, AsyncTransfer callback, object state, RateLimiter limiter, ConnectionMonitor managerMonitor, ConnectionMonitor peerMonitor) { Connection = connection; Buffer = buffer; Offset = offset; Count = 0; Callback = callback; ManagerMonitor = managerMonitor; PeerMonitor = peerMonitor; RateLimiter = limiter; State = state; Total = total; }
internal PeerId(Peer peer, TorrentManager manager) { LastReviewUploadRate = 0; LastReviewDownloadRate = 0; BytesUploadedAtLastReview = 0; BytesDownloadedAtLastReview = 0; if (peer == null) throw new ArgumentNullException("peer"); suggestedPieces = new MonoTorrentCollection<int>(); amChoking = true; isChoking = true; IsAllowedFastPieces = new MonoTorrentCollection<int>(); AmAllowedFastPieces = new MonoTorrentCollection<int>(); lastMessageReceived = DateTime.Now; lastMessageSent = DateTime.Now; this.peer = peer; MaxPendingRequests = 2; MaxSupportedPendingRequests = 50; monitor = new ConnectionMonitor(); sendQueue = new MonoTorrentCollection<PeerMessage>(12); ExtensionSupports = new ExtensionSupports(); TorrentManager = manager; InitializeTyrant(); }
internal static void EnqueueSend(IConnection connection, ArraySegment<byte> buffer, int offset, int count, AsyncTransfer callback, object state, RateLimiter limiter, ConnectionMonitor managerMonitor, ConnectionMonitor peerMonitor) { EnqueueSend(connection, buffer.Array, buffer.Offset + offset, count, callback, state, limiter, managerMonitor, peerMonitor); }
public static async Task SendMessageAsync(IConnection connection, IEncryption encryptor, PeerMessage message, IRateLimiter rateLimiter, ConnectionMonitor peerMonitor, ConnectionMonitor managerMonitor) { int count = message.ByteLength; var buffer = ClientEngine.BufferManager.GetBuffer(count); try { message.Encode(buffer, 0); encryptor.Encrypt(buffer, 0, count); await NetworkIO.SendAsync(connection, buffer, 0, count, rateLimiter, peerMonitor, managerMonitor).ConfigureAwait(false); } finally { ClientEngine.BufferManager.FreeBuffer(ref buffer); } }
public static async Task SendMessageAsync(IConnection connection, IEncryption encryptor, PeerMessage message, IRateLimiter rateLimiter, ConnectionMonitor peerMonitor, ConnectionMonitor managerMonitor) { int count = message.ByteLength; var buffer = ClientEngine.BufferManager.GetBuffer(count); try { var pieceMessage = message as PieceMessage; message.Encode(buffer, 0); encryptor.Encrypt(buffer, 0, count); // Assume protocol first, then swap it to data once we successfully send the data bytes. await NetworkIO.SendAsync(connection, buffer, 0, count, pieceMessage == null?null : rateLimiter, peerMonitor?.DataUp, managerMonitor?.DataUp).ConfigureAwait(false); if (pieceMessage != null) { peerMonitor?.ProtocolUp.AddDelta(-pieceMessage.RequestLength); managerMonitor?.ProtocolUp.AddDelta(-pieceMessage.RequestLength); peerMonitor?.DataUp.AddDelta(pieceMessage.RequestLength); managerMonitor?.DataUp.AddDelta(pieceMessage.RequestLength); } } finally { ClientEngine.BufferManager.FreeBuffer(buffer); } }
public static async Task <PeerMessage> ReceiveMessageAsync(IConnection connection, IEncryption decryptor, IRateLimiter rateLimiter, ConnectionMonitor monitor, TorrentManager manager) { byte[] messageLengthBuffer = null; byte[] messageBuffer = null; int messageLength = 4; int messageBody; try { messageLengthBuffer = ClientEngine.BufferManager.GetBuffer(messageLength); await NetworkIO.ReceiveAsync(connection, messageLengthBuffer, 0, messageLength, rateLimiter, monitor?.ProtocolDown, manager?.Monitor.ProtocolDown).ConfigureAwait(false); decryptor.Decrypt(messageLengthBuffer, 0, messageLength); messageBody = IPAddress.HostToNetworkOrder(BitConverter.ToInt32(messageLengthBuffer, 0)); if (messageBody < 0 || messageBody > MaxMessageLength) { connection.Dispose(); throw new ProtocolException($"Invalid message length received. Value was '{messageBody}'"); } if (messageBody == 0) { return(new KeepAliveMessage()); } messageBuffer = ClientEngine.BufferManager.GetBuffer(messageBody + messageLength); Buffer.BlockCopy(messageLengthBuffer, 0, messageBuffer, 0, messageLength); } finally { ClientEngine.BufferManager.FreeBuffer(messageLengthBuffer); } try { // Always assume protocol first, then convert to data when we what message it is! await NetworkIO.ReceiveAsync(connection, messageBuffer, messageLength, messageBody, rateLimiter, monitor?.ProtocolDown, manager?.Monitor.ProtocolDown).ConfigureAwait(false); decryptor.Decrypt(messageBuffer, messageLength, messageBody); // FIXME: manager should never be null, except some of the unit tests do that. var data = PeerMessage.DecodeMessage(messageBuffer, 0, messageLength + messageBody, manager?.Torrent); if (data is PieceMessage msg) { monitor?.ProtocolDown.AddDelta(-msg.RequestLength); manager?.Monitor.ProtocolDown.AddDelta(-msg.RequestLength); monitor?.DataDown.AddDelta(msg.RequestLength); manager?.Monitor.DataDown.AddDelta(msg.RequestLength); } return(data); } finally { ClientEngine.BufferManager.FreeBuffer(messageBuffer); } }
public static void EnqueueReceiveMessage(IConnection connection, IEncryption decryptor, IRateLimiter rateLimiter, ConnectionMonitor monitor, TorrentManager manager, AsyncMessageReceivedCallback callback, object state) { // FIXME: Hardcoded number int count = 4; var buffer = ClientEngine.BufferManager.GetBuffer(count); var data = receiveCache.Dequeue().Initialise(connection, decryptor, rateLimiter, monitor, manager, buffer, callback, state); NetworkIO.EnqueueReceive(connection, buffer, 0, count, rateLimiter, monitor, data.ManagerMonitor, MessageLengthReceivedCallback, data); }
public static void EnqueueReceive(IConnection connection, byte[] buffer, int offset, int count, IRateLimiter rateLimiter, ConnectionMonitor peerMonitor, ConnectionMonitor managerMonitor, AsyncIOCallback callback, object state) { var data = transferCache.Dequeue() .Initialise(connection, buffer, offset, count, callback, state, rateLimiter, peerMonitor, managerMonitor); lock (receiveQueue) ReceiveOrEnqueue(data); }
public ReceiveMessageState Initialise(IConnection connection, IEncryption decryptor, IRateLimiter limiter, ConnectionMonitor peerMonitor, TorrentManager manager, byte[] buffer, AsyncMessageReceivedCallback callback, object state) { Connection = connection; Decryptor = decryptor; Manager = manager; Buffer = buffer; PeerMonitor = peerMonitor; RateLimiter = limiter; ManagerMonitor = manager == null ? null : manager.Monitor; Callback = callback; State = state; return(this); }
public static async Task SendAsync(IConnection connection, byte [] buffer, int offset, int count, IRateLimiter rateLimiter, ConnectionMonitor peerMonitor, ConnectionMonitor managerMonitor) { await IOLoop; int remaining = count; while (remaining > 0) { int transferred; if (rateLimiter != null && !rateLimiter.Unlimited && !rateLimiter.TryProcess(Math.Min(ChunkLength, remaining))) { var tcs = new TaskCompletionSource <int> (); await IOLoop; sendQueue.Enqueue(new QueuedIO(connection, buffer, offset, Math.Min(ChunkLength, remaining), rateLimiter, tcs)); transferred = await tcs.Task.ConfigureAwait(false); } else { transferred = await connection.SendAsync(buffer, offset, remaining).ConfigureAwait(false); } if (transferred == 0) { throw new Exception("Socket is dead"); } peerMonitor?.BytesSent(transferred, count > 8000 ? TransferType.Data : TransferType.Protocol); managerMonitor?.BytesSent(transferred, count > 8000 ? TransferType.Data : TransferType.Protocol); offset += transferred; remaining -= transferred; } }
internal async void ReceiveMessagesAsync(IConnection2 connection, IEncryption decryptor, RateLimiterGroup downloadLimiter, ConnectionMonitor monitor, TorrentManager torrentManager, PeerId id) { try { while (true) { Messages.PeerMessage message = await PeerIO.ReceiveMessageAsync(connection, decryptor, downloadLimiter, monitor, torrentManager); if (id.Disposed) { if (message is PieceMessage msg) { ClientEngine.BufferPool.Return(msg.Data); } } else { id.LastMessageReceived.Restart(); message.Handle(torrentManager, id); } } } catch { CleanupSocket(torrentManager, id); } }
internal async void ReceiveMessagesAsync(IConnection2 connection, IEncryption decryptor, RateLimiterGroup downloadLimiter, ConnectionMonitor monitor, TorrentManager torrentManager, PeerId id) { try { while (true) { Messages.PeerMessage message = await PeerIO.ReceiveMessageAsync(connection, decryptor, downloadLimiter, monitor, torrentManager.Monitor, torrentManager.Torrent); if (id.Disposed) { if (message is PieceMessage msg) { msg.DataReleaser.Dispose(); } break; } else { id.LastMessageReceived.Restart(); torrentManager.Mode.HandleMessage(id, message); } } } catch { CleanupSocket(torrentManager, id); } }
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); } }
public static async Task <PeerMessage> ReceiveMessageAsync(IConnection connection, IEncryption decryptor, IRateLimiter rateLimiter, ConnectionMonitor monitor, TorrentManager manager) { var messageLengthBuffer = BufferManager.EmptyBuffer; var messageBuffer = BufferManager.EmptyBuffer; try { int messageLength = 4; ClientEngine.BufferManager.GetBuffer(ref messageLengthBuffer, messageLength); await NetworkIO.ReceiveAsync(connection, messageLengthBuffer, 0, messageLength, rateLimiter, monitor, manager?.Monitor).ConfigureAwait(false); decryptor.Decrypt(messageLengthBuffer, 0, messageLength); int messageBody = IPAddress.HostToNetworkOrder(BitConverter.ToInt32(messageLengthBuffer, 0));; if (messageBody < 0 || messageBody > MaxMessageLength) { throw new Exception($"Invalid message length received. Value was '{messageBody}'"); } if (messageBody == 0) { return(new KeepAliveMessage()); } ClientEngine.BufferManager.GetBuffer(ref messageBuffer, messageBody + messageLength); Buffer.BlockCopy(messageLengthBuffer, 0, messageBuffer, 0, messageLength); ClientEngine.BufferManager.FreeBuffer(ref messageLengthBuffer); await NetworkIO.ReceiveAsync(connection, messageBuffer, messageLength, messageBody, rateLimiter, monitor, manager?.Monitor).ConfigureAwait(false); decryptor.Decrypt(messageBuffer, messageLength, messageBody); return(PeerMessage.DecodeMessage(messageBuffer, 0, messageLength + messageBody, manager)); } finally { ClientEngine.BufferManager.FreeBuffer(ref messageLengthBuffer); ClientEngine.BufferManager.FreeBuffer(ref messageBuffer); } }
internal PeerId(Peer peer, TorrentManager manager) { if (peer == null) throw new ArgumentNullException("peer"); this.suggestedPieces = new MonoTorrentCollection<int>(); this.amChoking = true; this.isChoking = true; this.isAllowedFastPieces = new MonoTorrentCollection<int>(); this.amAllowedFastPieces = new MonoTorrentCollection<int>(); this.lastMessageReceived = DateTime.Now; this.lastMessageSent = DateTime.Now; this.peer = peer; this.monitor = new ConnectionMonitor(); this.sendQueue = new MonoTorrentCollection<PeerMessage>(12); TorrentManager = manager; InitializeTyrant(); }
public static void EnqueueSendMessage(IConnection connection, IEncryption encryptor, PeerMessage message, IRateLimiter rateLimiter, ConnectionMonitor peerMonitor, ConnectionMonitor managerMonitor, AsyncIOCallback callback, object state) { int count = message.ByteLength; var buffer = ClientEngine.BufferManager.GetBuffer(count); message.Encode(buffer, 0); encryptor.Encrypt(buffer, 0, count); var data = sendCache.Dequeue().Initialise(buffer, callback, state); NetworkIO.EnqueueSend(connection, buffer, 0, count, rateLimiter, peerMonitor, managerMonitor, EndSendCallback, data); }