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);
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; } }
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]); } }