/// <inheritdoc /> public override async Task <IFtpResponse> Process(FtpCommand command, CancellationToken cancellationToken) { // Reset the login var loginStateMachine = Connection.ConnectionServices.GetRequiredService <IFtpLoginStateMachine>(); loginStateMachine.Reset(); // Remember old features var fileSystemFeature = Connection.Features.Get <IFileSystemFeature>(); var connectionFeature = Connection.Features.Get <IConnectionFeature>(); var secureConnectionFeature = Connection.Features.Get <ISecureConnectionFeature>(); // Reset to empty file system fileSystemFeature.FileSystem = new EmptyUnixFileSystem(); fileSystemFeature.Path.Clear(); // Remove the control connection encryption await secureConnectionFeature.CloseEncryptedControlStream(cancellationToken) .ConfigureAwait(false); // Dispose and remove all features (if disposable) var setFeatureMethod = Connection.Features.GetType().GetTypeInfo().GetDeclaredMethod("Set"); foreach (var featureItem in Connection.Features) { if (!(featureItem.Value is IDisposable disposableFeature)) { continue; } try { disposableFeature.Dispose(); } catch (Exception ex) { // Ignore exceptions _logger?.LogWarning( ex, "Failed to feature of type {featureType}: {errorMessage}", featureItem.Key, ex.Message); } // Remove from features collection var setMethod = setFeatureMethod.MakeGenericMethod(featureItem.Key); setMethod.Invoke(Connection.Features, new object[] { null }); } // Set the default FTP data connection feature var activeDataConnectionFeatureFactory = Connection.ConnectionServices.GetRequiredService <ActiveDataConnectionFeatureFactory>(); var dataConnectionFeature = await activeDataConnectionFeatureFactory.CreateFeatureAsync(null, connectionFeature.RemoteAddress, _dataPort) .ConfigureAwait(false); Connection.Features.Set(dataConnectionFeature); return(new FtpResponseTextBlock(220, _serverMessages.GetBannerMessage())); }
/// <inheritdoc /> public override async Task <IFtpResponse?> Process(FtpCommand command, CancellationToken cancellationToken) { // User-Logout var authorizationInformationFeature = Connection.Features.Get <IAuthorizationInformationFeature>(); var user = authorizationInformationFeature.FtpUser; var membershipProvider = authorizationInformationFeature.MembershipProvider; if (user != null && membershipProvider is IMembershipProviderAsync membershipProviderAsync) { await membershipProviderAsync.LogOutAsync(user, cancellationToken); } // Reset the login var loginStateMachine = Connection.ConnectionServices.GetRequiredService <IFtpLoginStateMachine>(); loginStateMachine.Reset(); // Reset encoding var encodingFeature = Connection.Features.Get <IEncodingFeature>(); encodingFeature.Reset(); // Remember old features var fileSystemFeature = Connection.Features.Get <IFileSystemFeature>(); var connectionFeature = Connection.Features.Get <IConnectionFeature>(); var secureConnectionFeature = Connection.Features.Get <ISecureConnectionFeature>(); // Reset to empty file system fileSystemFeature.FileSystem = new EmptyUnixFileSystem(); fileSystemFeature.Path.Clear(); // Remove the control connection encryption await secureConnectionFeature.CloseEncryptedControlStream(cancellationToken) .ConfigureAwait(false); // Dispose and remove all features (if disposable) foreach (var featureItem in Connection.Features) { try { switch (featureItem.Value) { case IFtpConnection _: // Never dispose the connection itself. break; case IFtpDataConnectionFeature f: await f.DisposeAsync().ConfigureAwait(false); break; case IDisposable disposable: disposable.Dispose(); break; } } catch (Exception ex) { // Ignore exceptions _logger?.LogWarning( ex, "Failed to dispose feature of type {FeatureType}: {ErrorMessage}", featureItem.Key, ex.Message); } // Remove from features collection Connection.Features[featureItem.Key] = null; } // Reset the FTP data connection configuration feature Connection.Features.Set <IFtpDataConnectionConfigurationFeature>(new FtpDataConnectionConfigurationFeature()); // Set the default FTP data connection feature var activeDataConnectionFeatureFactory = Connection.ConnectionServices.GetRequiredService <ActiveDataConnectionFeatureFactory>(); var dataConnectionFeature = await activeDataConnectionFeatureFactory.CreateFeatureAsync(null, connectionFeature.RemoteEndPoint, _dataPort) .ConfigureAwait(false); Connection.Features.Set(dataConnectionFeature); return(new FtpResponseTextBlock(220, _serverMessages.GetBannerMessage())); }