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