public FtpTelnetInputParser(FtpCommandCollector collector) { _collector = collector; }
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(); } } }