/// <summary> /// Initializes a new instance of the <see cref="FtpConnection"/> class. /// </summary> /// <param name="socketAccessor">The accessor to get the socket used to communicate with the client.</param> /// <param name="options">The options for the FTP connection.</param> /// <param name="portOptions">The <c>PORT</c> command options.</param> /// <param name="connectionAccessor">The accessor to get the connection that is active during the <see cref="FtpCommandHandler.Process"/> method execution.</param> /// <param name="catalogLoader">The catalog loader for the FTP server.</param> /// <param name="serverCommandExecutor">The executor for server commands.</param> /// <param name="serviceProvider">The service provider for the connection.</param> /// <param name="secureDataConnectionWrapper">Wraps a data connection into an SSL stream.</param> /// <param name="sslStreamWrapperFactory">The SSL stream wrapper factory.</param> /// <param name="logger">The logger for the FTP connection.</param> public FtpConnection( TcpSocketClientAccessor socketAccessor, IOptions <FtpConnectionOptions> options, IOptions <PortCommandOptions> portOptions, IFtpConnectionAccessor connectionAccessor, IFtpCatalogLoader catalogLoader, IServerCommandExecutor serverCommandExecutor, IServiceProvider serviceProvider, SecureDataConnectionWrapper secureDataConnectionWrapper, ISslStreamWrapperFactory sslStreamWrapperFactory, ILogger <FtpConnection>?logger = null) { var socket = socketAccessor.TcpSocketClient ?? throw new InvalidOperationException("The socket to communicate with the client was not set"); ConnectionServices = serviceProvider; ConnectionId = "FTP-" + Guid.NewGuid().ToString("N"); _dataPort = portOptions.Value.DataPort; var remoteEndPoint = _remoteEndPoint = (IPEndPoint)socket.Client.RemoteEndPoint; #pragma warning disable 618 RemoteAddress = new Address(remoteEndPoint.Address.ToString(), remoteEndPoint.Port); #pragma warning restore 618 var properties = new Dictionary <string, object?> { ["RemoteAddress"] = remoteEndPoint.ToString(), ["RemoteIp"] = remoteEndPoint.Address.ToString(), ["RemotePort"] = remoteEndPoint.Port, ["ConnectionId"] = ConnectionId, }; _loggerScope = logger?.BeginScope(properties); _socket = socket; _connectionAccessor = connectionAccessor; _serverCommandExecutor = serverCommandExecutor; _secureDataConnectionWrapper = secureDataConnectionWrapper; _serverCommandChannel = Channel.CreateBounded <IServerCommand>(new BoundedChannelOptions(3)); _logger = logger; var parentFeatures = new FeatureCollection(); var connectionFeature = new ConnectionFeature( (IPEndPoint)socket.Client.LocalEndPoint, remoteEndPoint); var secureConnectionFeature = new SecureConnectionFeature(); var applicationInputPipe = new Pipe(); var applicationOutputPipe = new Pipe(); var socketPipe = new DuplexPipe(_socketCommandPipe.Reader, _socketResponsePipe.Writer); var connectionPipe = new DuplexPipe(applicationOutputPipe.Reader, applicationInputPipe.Writer); var originalStream = socketAccessor.TcpSocketStream ?? socket.GetStream(); _streamReaderService = new ConnectionClosingNetworkStreamReader( originalStream, _socketCommandPipe.Writer, _cancellationTokenSource); _streamWriterService = new StreamPipeWriterService( originalStream, _socketResponsePipe.Reader, _cancellationTokenSource.Token); _networkStreamFeature = new NetworkStreamFeature( new SecureConnectionAdapter( socketPipe, connectionPipe, sslStreamWrapperFactory, _cancellationTokenSource.Token), applicationOutputPipe.Writer); parentFeatures.Set <IConnectionFeature>(connectionFeature); parentFeatures.Set <ISecureConnectionFeature>(secureConnectionFeature); parentFeatures.Set <IServerCommandFeature>(new ServerCommandFeature(_serverCommandChannel)); parentFeatures.Set <INetworkStreamFeature>(_networkStreamFeature); var features = new FeatureCollection(parentFeatures); #pragma warning disable 618 Data = new FtpConnectionData( options.Value.DefaultEncoding ?? Encoding.ASCII, features, catalogLoader); #pragma warning restore 618 Features = features; _commandReader = ReadCommandsFromPipeline( applicationInputPipe.Reader, _ftpCommandChannel.Writer, _cancellationTokenSource.Token); }
/// <summary> /// Initializes a new instance of the <see cref="FtpConnection"/> class. /// </summary> /// <param name="socket">The socket to use to communicate with the client.</param> /// <param name="options">The options for the FTP connection.</param> /// <param name="portOptions">The <c>PORT</c> command options.</param> /// <param name="connectionAccessor">The accessor to get the connection that is active during the <see cref="FtpCommandHandler.Process"/> method execution.</param> /// <param name="catalogLoader">The catalog loader for the FTP server.</param> /// <param name="serverCommandExecutor">The executor for server commands.</param> /// <param name="serviceProvider">The service provider for the connection.</param> /// <param name="secureDataConnectionWrapper">Wraps a data connection into an SSL stream.</param> /// <param name="serverMessages">The server messages.</param> /// <param name="sslStreamWrapperFactory">The SSL stream wrapper factory.</param> /// <param name="logger">The logger for the FTP connection.</param> public FtpConnection( [NotNull] TcpClient socket, [NotNull] IOptions <FtpConnectionOptions> options, [NotNull] IOptions <PortCommandOptions> portOptions, [NotNull] IFtpConnectionAccessor connectionAccessor, [NotNull] IFtpCatalogLoader catalogLoader, [NotNull] IServerCommandExecutor serverCommandExecutor, [NotNull] IServiceProvider serviceProvider, [NotNull] SecureDataConnectionWrapper secureDataConnectionWrapper, [NotNull] IFtpServerMessages serverMessages, [NotNull] ISslStreamWrapperFactory sslStreamWrapperFactory, [CanBeNull] ILogger <FtpConnection> logger = null) { ConnectionServices = serviceProvider; ConnectionId = "FTP-" + Guid.NewGuid().ToString("N"); _dataPort = portOptions.Value.DataPort; var endpoint = (IPEndPoint)socket.Client.RemoteEndPoint; var remoteAddress = _remoteAddress = new Address(endpoint.Address.ToString(), endpoint.Port); var properties = new Dictionary <string, object> { ["RemoteAddress"] = remoteAddress.ToString(true), ["RemoteIp"] = remoteAddress.IPAddress?.ToString(), ["RemotePort"] = remoteAddress.Port, ["ConnectionId"] = ConnectionId, }; _loggerScope = logger?.BeginScope(properties); _socket = socket; _connectionAccessor = connectionAccessor; _serverCommandExecutor = serverCommandExecutor; _secureDataConnectionWrapper = secureDataConnectionWrapper; _serverMessages = serverMessages; _serverCommandChannel = Channel.CreateBounded <IServerCommand>(new BoundedChannelOptions(3)); _logger = logger; var parentFeatures = new FeatureCollection(); var connectionFeature = new ConnectionFeature( (IPEndPoint)socket.Client.LocalEndPoint, remoteAddress); var secureConnectionFeature = new SecureConnectionFeature(socket); var applicationInputPipe = new Pipe(); var applicationOutputPipe = new Pipe(); var socketPipe = new DuplexPipe(_socketCommandPipe.Reader, _socketResponsePipe.Writer); var connectionPipe = new DuplexPipe(applicationOutputPipe.Reader, applicationInputPipe.Writer); _networkStreamFeature = new NetworkStreamFeature( new SecureConnectionAdapter( socketPipe, connectionPipe, sslStreamWrapperFactory, _cancellationTokenSource.Token), new ConnectionClosingNetworkStreamReader( secureConnectionFeature.OriginalStream, _socketCommandPipe.Writer, _cancellationTokenSource), new StreamPipeWriterService( secureConnectionFeature.OriginalStream, _socketResponsePipe.Reader, _cancellationTokenSource.Token), applicationOutputPipe.Writer); parentFeatures.Set <IConnectionFeature>(connectionFeature); parentFeatures.Set <ISecureConnectionFeature>(secureConnectionFeature); parentFeatures.Set <IServerCommandFeature>(new ServerCommandFeature(_serverCommandChannel)); parentFeatures.Set <INetworkStreamFeature>(_networkStreamFeature); var features = new FeatureCollection(parentFeatures); #pragma warning disable 618 Data = new FtpConnectionData( options.Value.DefaultEncoding ?? Encoding.ASCII, features, catalogLoader); #pragma warning restore 618 Features = features; _commandReader = ReadCommandsFromPipeline( applicationInputPipe.Reader, _ftpCommandChannel.Writer, _cancellationTokenSource.Token); }