private async Task PublishDataToTrafficReaderAsync(TcpDataReader trafficReader) { try { #if NETSTANDARD2_1 var buffer = await trafficReader.AllocateBufferToWriteAsync(_cancellationToken.Token); var readSize = await SocketStream.ReadAsync(buffer, _cancellationToken.Token); while (readSize > 0) { SocketStatistic.WeHaveReceiveEvent(readSize); trafficReader.CommitWrittenData(readSize); buffer = await trafficReader.AllocateBufferToWriteAsync(_cancellationToken.Token); readSize = await SocketStream.ReadAsync(buffer, _cancellationToken.Token); } #else var buffer = await trafficReader.AllocateBufferToWriteLegacyAsync(_cancellationToken.Token); var readSize = await SocketStream.ReadAsync(buffer.buffer, buffer.start, buffer.len, _cancellationToken.Token); while (readSize > 0) { SocketStatistic.WeHaveReceiveEvent(readSize); trafficReader.CommitWrittenData(readSize); buffer = await trafficReader.AllocateBufferToWriteLegacyAsync(_cancellationToken.Token); readSize = await SocketStream.ReadAsync(buffer.buffer, buffer.start, buffer.len, _cancellationToken.Token); } #endif } catch (Exception e) { Log.InvokeExceptionLog(this, e, true); } finally { Log.InvokeInfoLog(this, "Disconnected from Traffic Reader Loop"); trafficReader.Stop(); } }
private async Task ProcessMessages() { Log?.Info($"Connected from {RemoteAddress.ToString(true)}"); using (var collector = new FtpCommandCollector(() => Encoding)) { await WriteAsync(new FtpResponse(220, "FTP Server Ready"), _cancellationTokenSource.Token); var buffer = new byte[1024]; try { Task <int> readTask = null; for (; ;) { if (readTask == null) { readTask = SocketStream.ReadAsync(buffer, 0, buffer.Length, _cancellationTokenSource.Token); } var tasks = new List <Task>() { readTask }; if (_activeBackgroundTask != null) { tasks.Add(_activeBackgroundTask); } Debug.WriteLine($"Waiting for {tasks.Count} tasks"); var completedTask = Task.WaitAny(tasks.ToArray(), _cancellationTokenSource.Token); Debug.WriteLine($"Task {completedTask} completed"); if (completedTask == 1) { var response = _activeBackgroundTask?.Result; if (response != null) { Write(response); } _activeBackgroundTask = null; } else { var bytesRead = readTask.Result; readTask = null; if (bytesRead == 0) { break; } var commands = collector.Collect(buffer, 0, bytesRead); foreach (var command in commands) { await ProcessMessage(command); } } } } catch (OperationCanceledException) { // Ignore the OperationCanceledException // This is normal during disconnects } catch (Exception ex) { Log?.Error(ex, "Failed to process connection"); } finally { Log?.Info($"Disconnection from {RemoteAddress.ToString(true)}"); _closed = true; Data.BackgroundCommandHandler.Cancel(); if (!ReferenceEquals(SocketStream, OriginalStream)) { SocketStream.Dispose(); SocketStream = OriginalStream; } _socket.Dispose(); OnClosed(); } } }
public async Task WhenSendingMessagesToEchoServer_ThenStatisticsAreUpdated( [LinuxInstance(InitializeScript = InitializeScripts.InstallEchoServer)] ResourceTask <InstanceLocator> vm, [Credential(Role = PredefinedRole.IapTunnelUser)] ResourceTask <ICredential> credential, [Values( 1, (int)DataMessage.MaxDataLength, (int)DataMessage.MaxDataLength * 2)] int length) { var message = new byte[length]; FillArray(message); var locator = await vm; var listener = SshRelayListener.CreateLocalListener( new IapTunnelingEndpoint( await credential, await vm, 7, IapTunnelingEndpoint.DefaultNetworkInterface, TestProject.UserAgent), new AllowAllRelayPolicy()); listener.ClientAcceptLimit = 1; // Terminate after first connection. listener.ListenAsync(CancellationToken.None).ContinueWith(_ => { }); var socket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp); socket.Connect(new IPEndPoint(IPAddress.Loopback, listener.LocalPort)); var clientStreamStats = new ConnectionStatistics(); var clientStream = new SocketStream(socket, clientStreamStats); using (var tokenSource = new CancellationTokenSource()) { // Write full payload. await clientStream.WriteAsync(message, 0, message.Length, tokenSource.Token); Assert.AreEqual(length, clientStreamStats.BytesTransmitted); // Read entire response. var response = new byte[length]; int totalBytesRead = 0; while (true) { var bytesRead = await clientStream.ReadAsync( response, totalBytesRead, response.Length - totalBytesRead, tokenSource.Token); totalBytesRead += bytesRead; if (bytesRead == 0 || totalBytesRead >= length) { break; } } await clientStream.CloseAsync(tokenSource.Token); await Task.Delay(50); Assert.AreEqual(length, totalBytesRead, "bytes read"); Assert.AreEqual(length, clientStreamStats.BytesReceived, "client received"); Assert.AreEqual(length, listener.Statistics.BytesReceived, "server received"); Assert.AreEqual(length, listener.Statistics.BytesTransmitted, "server sent"); } }