Beispiel #1
0
        public async Task ReceiveTwoKeepAlives()
        {
            var message = new KeepAliveMessage();
            var buffer  = message.Encode();
            var handle  = new AutoResetEvent(false);

            await NetworkIO.SendAsync(Outgoing, buffer, 0, buffer.Length, null, null, null);

            var sendTask = NetworkIO.SendAsync(Outgoing, buffer, 0, buffer.Length, null, null, null);

            var task = PeerIO.ReceiveMessageAsync(Incoming, PlainTextEncryption.Instance, null, null, null);

            Assert.IsTrue(task.Wait(TimeSpan.FromSeconds(2)), "#Should receive first message");

            task = PeerIO.ReceiveMessageAsync(Incoming, PlainTextEncryption.Instance, null, null, null);
            Assert.IsTrue(task.Wait(TimeSpan.FromSeconds(2)), "#Should receive second message");
            await sendTask;
        }
Beispiel #2
0
        internal void ConnectToPeer(TorrentManager manager, Peer peer)
        {
            // Connect to the peer.
            IConnection connection = ConnectionFactory.Create(peer.ConnectionUri);

            if (connection == null)
            {
                return;
            }

            peer.LastConnectionAttempt = DateTime.Now;
            AsyncConnectState c = new AsyncConnectState(manager, peer, connection);

            pendingConnects.Add(c);

            manager.Peers.ConnectingToPeers.Add(peer);
            NetworkIO.EnqueueConnect(connection, endCreateConnectionCallback, c);
        }
Beispiel #3
0
        private async Task CompleteSendOrReceiveFirst(byte[] buffer, Task receiveTask)
        {
            while (requests.Messages.Count > 0)
            {
                await receiveTask;
                int   size = IPAddress.NetworkToHostOrder(BitConverter.ToInt32(buffer, 0));

                await NetworkIO.ReceiveAsync(connection, buffer, 4, size, null, null, null);

                PieceMessage   m       = (PieceMessage)PeerMessage.DecodeMessage(buffer, 0, size + 4, rig.Manager);
                RequestMessage request = (RequestMessage)requests.Messages[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[i + 13] != (byte)(m.PieceIndex * rig.Torrent.PieceLength + m.StartOffset + i))
                    {
                        throw new Exception("Corrupted data received");
                    }
                }

                requests.Messages.RemoveAt(0);

                if (requests.Messages.Count == 0)
                {
                    break;
                }
                else
                {
                    receiveTask = NetworkIO.ReceiveAsync(connection, buffer, 0, 4, null, null, null);
                }
            }

            Uri baseUri = new Uri(ListenerURL);

            baseUri = new Uri(baseUri, rig.Manager.Torrent.Name + "/");
            if (rig.Manager.Torrent.Files.Length > 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]);
            }
        }
Beispiel #4
0
        public async Task DisposeBeforeReceive()
        {
            var listener = new TcpListener(IPAddress.Loopback, 0);

            listener.Start();
            try {
                using var c = new IPV4Connection(new Uri($"ipv4://127.0.0.1:{((IPEndPoint) listener.LocalEndpoint).Port}"));
                var connectTask = NetworkIO.ConnectAsync(c);

                var receivingSocket = await listener.AcceptSocketAsync().WithTimeout();

                await connectTask.WithTimeout();

                c.Dispose();
                Assert.AreEqual(0, await c.ReceiveAsync(new ByteBuffer(123), 0, 123).WithTimeout());
            } finally {
                listener.Stop();
            }
        }
        public async Task ReceiveData_RateLimited()
        {
            // Allow 1 megabyte worth of data
            var oneMegabyte = 1 * 1024 * 1024;
            var limiter     = new RateLimiter();

            limiter.UpdateChunks(oneMegabyte, oneMegabyte, NetworkIO.ChunkLength);

            using var r1 = MemoryPool.Default.Rent(oneMegabyte, out Memory <byte> sendBuffer);
            using var r2 = MemoryPool.Default.Rent(oneMegabyte, out Memory <byte> receiveBuffer);

            await Outgoing.SendAsync(sendBuffer);

            await NetworkIO.ReceiveAsync(Incoming, receiveBuffer, limiter, null, null);

            var expectedChunks = (int)Math.Ceiling(oneMegabyte / (double)NetworkIO.ChunkLength);

            Assert.AreEqual(expectedChunks, Incoming.Receives.Count, "#1");
        }
Beispiel #6
0
        public async Task InvalidMessage()
        {
            Buffer.BlockCopy(BitConverter.GetBytes(IPAddress.HostToNetworkOrder(16)), 0, data, 0, 4);
            for (int i = 4; i < 16; i++)
            {
                data[i] = byte.MaxValue;
            }
            var task = PeerIO.ReceiveMessageAsync(Incoming, PlainTextEncryption.Instance, null, null, null);
            await NetworkIO.SendAsync(Outgoing, data, 0, 20, null, null, null);

            try
            {
                await task;
                Assert.Fail("An exception should've been thrown");
            }
            catch
            {
            }
        }
Beispiel #7
0
        public void DoSend(bool slowOutgoing, bool slowIncoming)
        {
            Incoming.SlowConnection = slowIncoming;
            Outgoing.SlowConnection = slowOutgoing;

            var task = NetworkIO.SendAsync(Outgoing, data, 0, data.Length, null, null, null);

            int received = 0;

            byte[] buffer = new byte[data.Length];
            while (received != buffer.Length)
            {
                int r = Incoming.Receive(buffer, received, buffer.Length - received);
                Assert.AreNotEqual(0, r, "#Received data");
                received += r;
            }
            Assert.IsTrue(task.Wait(TimeSpan.FromSeconds(1)), "Data should be all sent");
            Assert.IsTrue(Toolbox.ByteMatch(buffer, data), "Data matches");
        }
Beispiel #8
0
        public void InvalidMessage()
        {
            bool             success = true;
            ManualResetEvent handle  = new ManualResetEvent(false);

            Buffer.BlockCopy(BitConverter.GetBytes(IPAddress.HostToNetworkOrder(16)), 0, data, 0, 4);
            for (int i = 4; i < 16; i++)
            {
                data [i] = byte.MaxValue;
            }
            PeerIO.EnqueueReceiveMessage(Incoming, new PlainTextEncryption(), null, null, null, (successful, count, state) => {
                success = successful;
                handle.Set();
            }, null);

            NetworkIO.EnqueueSend(Outgoing, data, 0, 20, null, null, null, delegate { }, null);
            Assert.IsTrue(handle.WaitOne(TimeSpan.FromSeconds(4)), "#Should have closed");;
            Assert.IsFalse(success, "#1");
        }
        public async Task DisposeBeforeReceive()
        {
            var listener = new TcpListener(IPAddress.Loopback, 0);

            listener.Start();
            try {
                using var c = Factories.Default.CreatePeerConnection(new Uri($"ipv4://127.0.0.1:{((IPEndPoint) listener.LocalEndpoint).Port}"));
                var connectTask = NetworkIO.ConnectAsync(c);

                var receivingSocket = await listener.AcceptSocketAsync().WithTimeout();

                await connectTask.WithTimeout();

                c.Dispose();
                using var releaser = MemoryPool.Default.Rent(123, out Memory <byte> buffer);
                Assert.AreEqual(0, await c.ReceiveAsync(buffer).WithTimeout());
            } finally {
                listener.Stop();
            }
        }
Beispiel #10
0
        public void ReceiveTwoKeepAlives()
        {
            var message = new KeepAliveMessage();
            var buffer  = message.Encode();
            var handle  = new AutoResetEvent(false);

            NetworkIO.EnqueueSend(Outgoing, buffer, 0, buffer.Length, null, null, null, delegate { }, null);
            NetworkIO.EnqueueSend(Outgoing, buffer, 0, buffer.Length, null, null, null, delegate { }, null);

            AsyncMessageReceivedCallback callback = (s, m, state) => {
                if (s && m is KeepAliveMessage)
                {
                    handle.Set();
                }
            };

            PeerIO.EnqueueReceiveMessage(Incoming, new PlainTextEncryption(), null, null, null, callback, null);
            Assert.IsTrue(handle.WaitOne(TimeSpan.FromSeconds(2)), "#Should receive first message");


            PeerIO.EnqueueReceiveMessage(Incoming, new PlainTextEncryption(), null, null, null, callback, null);
            Assert.IsTrue(handle.WaitOne(TimeSpan.FromSeconds(2)), "#Should receive second message");
        }
Beispiel #11
0
        public void DoSend(bool slowOutgoing, bool slowIncoming)
        {
            Incoming.SlowConnection = slowIncoming;
            Outgoing.SlowConnection = slowOutgoing;

            var handle = new ManualResetEvent(false);

            NetworkIO.EnqueueSend(Outgoing, data, 0, data.Length, null, null, null, delegate {
                handle.Set();
            }, null);

            int received = 0;

            byte[] buffer = new byte [data.Length];
            while (received != buffer.Length)
            {
                int r = Incoming.Receive(buffer, received, buffer.Length - received);
                Assert.AreNotEqual(0, r, "#Received data");
                received += r;
            }
            Assert.IsTrue(handle.WaitOne(TimeSpan.FromSeconds(1)), "Data should be all sent");
            Assert.IsTrue(Toolbox.ByteMatch(buffer, data), "Data matches");
        }
Beispiel #12
0
        async Task DoSend(bool slowOutgoing, bool slowIncoming)
        {
            Incoming.SlowConnection = slowIncoming;
            Outgoing.SlowConnection = slowOutgoing;

            var data = new byte[16384];

            new Random().NextBytes(data);
            var task = NetworkIO.SendAsync(Outgoing, data, 0, data.Length, null, null, null);

            int received = 0;

            byte[] buffer = new byte[data.Length];
            while (received != buffer.Length)
            {
                int r = await Incoming.ReceiveAsync(buffer, received, buffer.Length - received);

                Assert.AreNotEqual(0, r, "#Received data");
                received += r;
            }
            Assert.DoesNotThrowAsync(() => task.WithTimeout(TimeSpan.FromSeconds(1)), "Data should be all sent");
            Assert.IsTrue(Toolbox.ByteMatch(buffer, data), "Data matches");
        }
        async Task DoSend(bool slowOutgoing, bool slowIncoming)
        {
            Incoming.SlowConnection = slowIncoming;
            Outgoing.SlowConnection = slowOutgoing;

            using var r1 = MemoryPool.Default.Rent(16384, out Memory <byte> sendBuffer);
            using var r2 = MemoryPool.Default.Rent(16384, out Memory <byte> receiveBuffer);
            new Random().NextBytes(sendBuffer.Span);
            var task = NetworkIO.SendAsync(Outgoing, sendBuffer, null, null, null);

            int received = 0;

            while (received != receiveBuffer.Length)
            {
                int r = await Incoming.ReceiveAsync(receiveBuffer.Slice(received));

                Assert.AreNotEqual(0, r, "#Received data");
                received += r;
            }
            await task.WithTimeout(TimeSpan.FromSeconds(10));

            Assert.IsTrue(receiveBuffer.Span.SequenceEqual(sendBuffer.Span), "Data matches");
        }
Beispiel #14
0
        public static async ReusableTask SendMessageAsync(IConnection connection, IEncryption encryptor, PeerMessage message, IRateLimiter rateLimiter, ConnectionMonitor peerMonitor, ConnectionMonitor managerMonitor, ByteBuffer buffer = null)
        {
            await MainLoop.SwitchToThreadpool();

            int count = message.ByteLength;

            using (buffer == null ? NetworkIO.BufferPool.Rent(count, out buffer) : default) {
                var pieceMessage = message as PieceMessage;
                message.Encode(buffer.Data, 0);
                encryptor.Encrypt(buffer.Data, 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?.ProtocolUp, managerMonitor?.ProtocolUp).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);
                }
            }
        }
Beispiel #15
0
        static void MessageLengthReceived(bool successful, int transferred, object state)
        {
            var data          = (ReceiveMessageState)state;
            int messageLength = -1;

            if (successful)
            {
                data.Decryptor.Decrypt(data.Buffer, 0, transferred);
                messageLength = IPAddress.HostToNetworkOrder(BitConverter.ToInt32(data.Buffer, 0));
            }

            if (!successful || messageLength < 0 || messageLength > MaxMessageLength)
            {
                ClientEngine.BufferManager.FreeBuffer(data.Buffer);
                data.Callback(false, null, data.State);
                receiveCache.Enqueue(data);
                return;
            }

            if (messageLength == 0)
            {
                ClientEngine.BufferManager.FreeBuffer(data.Buffer);
                data.Callback(true, new KeepAliveMessage(), data.State);
                receiveCache.Enqueue(data);
                return;
            }

            var buffer = ClientEngine.BufferManager.GetBuffer(messageLength + transferred);

            Buffer.BlockCopy(data.Buffer, 0, buffer, 0, transferred);
            ClientEngine.BufferManager.FreeBuffer(data.Buffer);
            data.Buffer = buffer;

            NetworkIO.EnqueueReceive(data.Connection, buffer, transferred, messageLength, data.RateLimiter, data.PeerMonitor,
                                     data.ManagerMonitor, MessageBodyReceivedCallback, data);
        }
Beispiel #16
0
        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);
            }
        }
Beispiel #17
0
        async Task DoSend(bool slowOutgoing, bool slowIncoming)
        {
            Incoming.SlowConnection = slowIncoming;
            Outgoing.SlowConnection = slowOutgoing;

            var data = new ByteBuffer(16384);

            new Random().NextBytes(data.Data);
            var task = NetworkIO.SendAsync(Outgoing, data, 0, data.Data.Length, null, null, null);

            int received = 0;
            var buffer   = new ByteBuffer(data.Data.Length);

            while (received != buffer.Data.Length)
            {
                int r = await Incoming.ReceiveAsync(buffer, received, buffer.Data.Length - received);

                Assert.AreNotEqual(0, r, "#Received data");
                received += r;
            }
            await task.WithTimeout(TimeSpan.FromSeconds(10));

            Assert.IsTrue(Toolbox.ByteMatch(buffer.Data, data.Data), "Data matches");
        }
        internal async void ConnectToPeer(TorrentManager manager, Peer peer)
        {
            // Connect to the peer.
            IConnection connection = ConnectionFactory.Create(peer.ConnectionUri);

            if (connection == null)
            {
                return;
            }

            var state = new AsyncConnectState(manager, connection, Stopwatch.StartNew());

            PendingConnects.Add(state);
            manager.Peers.ConnectingToPeers.Add(peer);

            bool succeeded;

            try {
                await NetworkIO.ConnectAsync(connection);

                succeeded = true;
            } catch {
                succeeded = false;
            }

            PendingConnects.Remove(state);
            if (manager.Engine == null ||
                !manager.Mode.CanAcceptConnections)
            {
                connection.Dispose();
                return;
            }

            try {
                manager.Peers.ConnectingToPeers.Remove(peer);
                if (!succeeded)
                {
                    Logger.Log(null, "ConnectionManager - Failed to connect{0}", peer);

                    manager.RaiseConnectionAttemptFailed(
                        new PeerConnectionFailedEventArgs(manager, peer, Direction.Outgoing, "EndCreateConnection"));

                    peer.FailedConnectionAttempts++;
                    connection.Dispose();
                    manager.Peers.BusyPeers.Add(peer);
                }
                else
                {
                    PeerId id = new PeerId(peer, manager);
                    id.Connection = connection;
                    manager.Peers.ActivePeers.Add(peer);

                    Logger.Log(id.Connection, "ConnectionManager - Connection opened");

                    ProcessFreshConnection(id);
                }
            } catch (Exception) {
                // FIXME: Do nothing now?
            } finally {
                // Try to connect to another peer
                TryConnect();
            }
        }
Beispiel #19
0
        async void ConnectToPeer(TorrentManager manager, Peer peer)
        {
            // Connect to the peer.
            var connection = Factories.CreatePeerConnection(peer.ConnectionUri);

            if (connection == null || peer.AllowedEncryption.Count == 0)
            {
                return;
            }

            var state = new AsyncConnectState(manager, connection, ValueStopwatch.StartNew());

            PendingConnects.Add(state);
            manager.Peers.ConnectingToPeers.Add(peer);

            bool succeeded;

            try {
                await NetworkIO.ConnectAsync(connection);

                succeeded = true;
            } catch {
                succeeded = false;
            }

            PendingConnects.Remove(state);
            manager.Peers.ConnectingToPeers.Remove(peer);
            if (manager.Disposed ||
                !manager.Mode.CanAcceptConnections ||
                OpenConnections > Settings.MaximumConnections ||
                manager.OpenConnections > manager.Settings.MaximumConnections)
            {
                manager.Peers.AvailablePeers.Add(peer);
                connection.Dispose();
                return;
            }

            try {
                if (!succeeded)
                {
                    peer.FailedConnectionAttempts++;
                    connection.Dispose();
                    manager.RaiseConnectionAttemptFailed(new ConnectionAttemptFailedEventArgs(peer, ConnectionFailureReason.Unreachable, manager));
                }
                else
                {
                    var id = new PeerId(peer, connection, new BitField(manager.Bitfield.Length).SetAll(false));
                    id.LastMessageReceived.Restart();
                    id.LastMessageSent.Restart();

                    logger.Info(id.Connection, "Connection opened");

                    ProcessNewOutgoingConnection(manager, id);
                }
            } catch {
                // FIXME: Do nothing now?
            } finally {
                // Try to connect to another peer
                TryConnect();
            }
        }
 public void DisposeBeforeConnect()
 {
     using var c = Factories.Default.CreatePeerConnection(new Uri($"ipv4://127.0.0.1:12345"));
     c.Dispose();
     Assert.ThrowsAsync <ObjectDisposedException> (async() => await NetworkIO.ConnectAsync(c));
 }