示例#1
0
        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);
            }
        }
示例#2
0
        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]);
            }
        }
示例#3
0
        public new Releaser Rent(int capacity, out SocketMemory memory)
        {
            var releaser = base.Rent(capacity, out memory);

            memory = memory.Slice(0, capacity);
            return(releaser);
        }
示例#4
0
        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);
示例#5
0
        /// <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)));
示例#6
0
        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;
            }
        }
示例#7
0
        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);
                }
            }
        }
示例#8
0
        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);
        }
示例#9
0
        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);
        }