public static async ReusableTask SendAsync(IPeerConnection connection, SocketMemory buffer, IRateLimiter rateLimiter, SpeedMonitor peerMonitor, SpeedMonitor managerMonitor) { await MainLoop.SwitchToThreadpool(); while (buffer.Length > 0) { int transferred; bool unlimited = rateLimiter?.Unlimited ?? true; int shouldRead = unlimited ? buffer.Length : Math.Min(ChunkLength, buffer.Length); if (rateLimiter != null && !unlimited && !rateLimiter.TryProcess(shouldRead)) { var tcs = new ReusableTaskCompletionSource <int> (); lock (sendQueue) sendQueue.Enqueue(new QueuedIO(connection, buffer.Slice(0, shouldRead), rateLimiter, tcs)); transferred = await tcs.Task.ConfigureAwait(false); } else { transferred = await connection.SendAsync(buffer.Slice(0, shouldRead)).ConfigureAwait(false); } if (transferred == 0) { throw new ConnectionClosedException("Socket send returned 0, indicating the connection has been closed."); } peerMonitor?.AddDelta(transferred); managerMonitor?.AddDelta(transferred); buffer = buffer.Slice(transferred); } }
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]); } }
public new Releaser Rent(int capacity, out SocketMemory memory) { var releaser = base.Rent(capacity, out memory); memory = memory.Slice(0, capacity); return(releaser); }
public static async ReusableTask <(PeerMessage message, PeerMessage.Releaser releaser)> ReceiveMessageAsync(IPeerConnection connection, IEncryption decryptor, IRateLimiter rateLimiter, ConnectionMonitor peerMonitor, ConnectionMonitor managerMonitor, ITorrentData torrentData, SocketMemory buffer) { await MainLoop.SwitchToThreadpool(); int messageHeaderLength = 4; int messageBodyLength; SocketMemory messageHeaderBuffer = buffer; SocketMemory messageBuffer = buffer; ByteBufferPool.Releaser messageHeaderReleaser = default; ByteBufferPool.Releaser messageBufferReleaser = default; if (messageHeaderBuffer.IsEmpty) { messageHeaderReleaser = NetworkIO.BufferPool.Rent(messageHeaderLength, out messageHeaderBuffer); } using (messageHeaderReleaser) { await NetworkIO.ReceiveAsync(connection, messageHeaderBuffer.Slice(0, messageHeaderLength), rateLimiter, peerMonitor?.ProtocolDown, managerMonitor?.ProtocolDown).ConfigureAwait(false); decryptor.Decrypt(messageHeaderBuffer.AsSpan(0, messageHeaderLength)); messageBodyLength = Message.ReadInt(messageHeaderBuffer.AsSpan()); if (messageBodyLength < 0 || messageBodyLength > MaxMessageLength) { connection.Dispose(); throw new ProtocolException($"Invalid message length received. Value was '{messageBodyLength}'"); } if (messageBodyLength == 0) { return(KeepAliveMessage.Instance, default);
/// <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; SocketMemory 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, socketMemory) = NetworkIO.BufferPool.Rent(msg.ByteLength); } var buffer = socketMemory.Slice(0, msg.ByteLength); if (msg is PieceMessage pm) { pm.SetData((default, buffer.Memory.Slice(buffer.Length - pm.RequestLength)));
protected async ReusableTask ReceiveMessageAsync(SocketMemory buffer) { if (buffer.Length == 0) { return; } if (!initialBuffer.IsEmpty) { int toCopy = Math.Min(initialBuffer.Length, buffer.Length); initialBuffer.Span.Slice(0, toCopy).CopyTo(buffer.AsSpan()); initialBuffer = initialBuffer.Slice(toCopy); if (toCopy != buffer.Length) { await NetworkIO.ReceiveAsync(socket, buffer.Slice(toCopy, buffer.Length - toCopy), null, null, null).ConfigureAwait(false); bytesReceived += buffer.Length - toCopy; } } else { await NetworkIO.ReceiveAsync(socket, buffer, null, null, null).ConfigureAwait(false); bytesReceived += buffer.Length; } }
async Task Send(SocketMemory buffer, int maxBytesPerChunk = -1) { if (maxBytesPerChunk == -1) { await NetworkIO.SendAsync(connection, buffer, null, null, null); } else { while (buffer.Length > 0) { var toSend = Math.Min(maxBytesPerChunk, buffer.Length); await NetworkIO.SendAsync(connection, buffer.Slice(0, toSend), null, null, null); buffer = buffer.Slice(toSend); } } }
public async ReusableTask <int> ReceiveAsync(SocketMemory buffer) { if (SlowConnection) { buffer = buffer.Slice(0, Math.Min(88, buffer.Length)); } var result = await ReadStream.ReadAsync(buffer.Memory); Receives.Add(result); return(ManualBytesReceived ?? result); }
public async ReusableTask <int> SendAsync(SocketMemory buffer) { if (SlowConnection) { buffer = buffer.Slice(0, Math.Min(88, buffer.Length)); } var data = buffer.Memory.ToArray(); await WriteStream.WriteAsync(data, 0, data.Length, CancellationToken.None); Sends.Add(buffer.Length); return(ManualBytesSent ?? buffer.Length); }