Add ForceDataPort configuration

Use StaticDataConnection
This commit is contained in:
2019-07-20 14:31:33 +02:00
parent b2189e63df
commit 01fbd0b74e
8 changed files with 156 additions and 23 deletions

View File

@@ -108,7 +108,7 @@ namespace DearFTP.Configurations
public void Save() public void Save()
{ {
var serializer = new SerializerBuilder().EmitDefaults().Build(); var serializer = new SerializerBuilder().Build();
File.WriteAllText(ConfigurationPath, serializer.Serialize(this)); File.WriteAllText(ConfigurationPath, serializer.Serialize(this));
} }

View File

@@ -7,6 +7,7 @@ namespace DearFTP.Configurations
class ServerConfiguration class ServerConfiguration
{ {
public ushort Port { get; set; } = 21; public ushort Port { get; set; } = 21;
public ushort ForceDataPort { get; set; } = 0;
public string MOTD { get; set; } = "DearFTP v0.1"; public string MOTD { get; set; } = "DearFTP v0.1";
public string LoginMessage { get; set; } = "Logged in as %user%"; public string LoginMessage { get; set; } = "Logged in as %user%";

View File

@@ -16,11 +16,11 @@ namespace DearFTP.Connection.Commands
switch (argument.ToUpper()) switch (argument.ToUpper())
{ {
case "C": case "C":
session.DataConnection.DesactivateTsl(); session.DataConnection.DesactivateTls();
stream.Send(ResponseCode.OK, "Data protection cleared."); stream.Send(ResponseCode.OK, "Data protection cleared.");
break; break;
case "P": case "P":
session.DataConnection.ActivateTsl(); session.DataConnection.ActivateTls();
stream.Send(ResponseCode.OK, "Data protection set."); stream.Send(ResponseCode.OK, "Data protection set.");
break; break;
default: default:

View File

@@ -11,15 +11,14 @@ using System.Threading.Tasks;
namespace DearFTP.Connection namespace DearFTP.Connection
{ {
class DataConnection class DynamicDataConnection : IDataConnection
{ {
public const int Timeout = 100_000; public const int Timeout = 10_000;
public TcpListener Listener { get; private set; }
public TcpClient Client { get; private set; }
public Stream Stream { get; private set; } public Stream Stream { get; private set; }
public bool IsTslProtected { get; private set; } public bool IsTslProtected { get; private set; }
public int Port => ((IPEndPoint)Listener.LocalEndpoint).Port;
public int Port => ((IPEndPoint)_listener.LocalEndpoint).Port;
public bool IsAvailable public bool IsAvailable
{ {
get get
@@ -41,9 +40,11 @@ namespace DearFTP.Connection
} }
} }
private TcpListener _listener;
private TcpClient _client;
private Task _acceptTask; private Task _acceptTask;
public DataConnection() public DynamicDataConnection()
{ {
IsTslProtected = false; IsTslProtected = false;
} }
@@ -51,41 +52,41 @@ namespace DearFTP.Connection
public void Create() public void Create()
{ {
// Clean old connections // Clean old connections
if (Client?.Connected == true) if (_client?.Connected == true)
{ {
Close(); Close();
} }
Listener = new TcpListener(IPAddress.Any, 0); _listener = new TcpListener(IPAddress.Any, 0);
Listener.Start(); _listener.Start();
} }
public void AcceptClient(bool authenticateAfter = false) public void AcceptClient()
{ {
_acceptTask = Listener.AcceptTcpClientAsync().ContinueWith(t => _acceptTask = _listener.AcceptTcpClientAsync().ContinueWith(t =>
{ {
Client = t.Result; _client = t.Result;
if (IsTslProtected) if (IsTslProtected)
{ {
var sslStream = new SslStream(Client.GetStream(), false); var sslStream = new SslStream(_client.GetStream(), false);
sslStream.AuthenticateAsServer(FtpServer.Instance.Configuration.Tls.X509Certificate, false, true); sslStream.AuthenticateAsServer(FtpServer.Instance.Configuration.Tls.X509Certificate, false, true);
Stream = sslStream; Stream = sslStream;
} }
else else
{ {
Stream = Client.GetStream(); Stream = _client.GetStream();
} }
}); });
} }
public void ActivateTsl() public void ActivateTls()
{ {
IsTslProtected = true; IsTslProtected = true;
} }
public void DesactivateTsl() public void DesactivateTls()
{ {
IsTslProtected = false; IsTslProtected = false;
} }
@@ -93,8 +94,8 @@ namespace DearFTP.Connection
public void Close() public void Close()
{ {
Stream.Close(); Stream.Close();
Client.Close(); _client.Close();
Listener.Stop(); _listener.Stop();
} }
} }
} }

View File

@@ -0,0 +1,21 @@
using System;
using System.Collections.Generic;
using System.IO;
using System.Text;
namespace DearFTP.Connection
{
interface IDataConnection
{
Stream Stream { get; }
int Port { get; }
bool IsTslProtected { get; }
bool IsAvailable { get; }
void Create();
void AcceptClient();
void ActivateTls();
void DesactivateTls();
void Close();
}
}

View File

@@ -22,7 +22,7 @@ namespace DearFTP.Connection
public Share[] WritablesShares { get; set; } public Share[] WritablesShares { get; set; }
public NavigablePath NavigablePath { get; set; } public NavigablePath NavigablePath { get; set; }
public FtpStream FtpStream { get; private set; } public FtpStream FtpStream { get; private set; }
public DataConnection DataConnection { get; set; } public IDataConnection DataConnection { get; set; }
public int RestartPosition { get; set; } public int RestartPosition { get; set; }
public bool IsTlsProtected { get; private set; } public bool IsTlsProtected { get; private set; }
public string CurrentWorkingDirectory => NavigablePath.CurrentDirectory; public string CurrentWorkingDirectory => NavigablePath.CurrentDirectory;
@@ -43,7 +43,7 @@ namespace DearFTP.Connection
Configuration = FtpServer.Instance.Configuration; Configuration = FtpServer.Instance.Configuration;
CommandsDispatcher = FtpServer.Instance.CommandsDispatcher; CommandsDispatcher = FtpServer.Instance.CommandsDispatcher;
Logger = FtpServer.Instance.Logger; Logger = FtpServer.Instance.Logger;
DataConnection = new DataConnection(); DataConnection = Configuration.Server.ForceDataPort == 0 ? (IDataConnection)new DynamicDataConnection() : new StaticDataConnection();
RestartPosition = 0; RestartPosition = 0;
IsTlsProtected = false; IsTlsProtected = false;
} }
@@ -94,6 +94,7 @@ namespace DearFTP.Connection
_sslStream?.Close(); _sslStream?.Close();
_networkStream.Close(); _networkStream.Close();
_client.Close(); _client.Close();
DataConnection.Close();
} }
} }
} }

View File

@@ -0,0 +1,108 @@
using System;
using System.IO;
using System.Net;
using System.Net.Security;
using System.Net.Sockets;
using System.Threading.Tasks;
namespace DearFTP.Connection
{
class StaticDataConnection : IDataConnection
{
public const int Timeout = 10_000;
public Stream Stream { get; private set; }
public bool IsTslProtected { get; private set; }
public int Port => ((IPEndPoint)_listener.LocalEndpoint).Port;
public bool IsAvailable
{
get
{
if (_acceptTask == null)
{
return false;
}
else if (_acceptTask.Wait(Timeout))
{
return true;
}
else
{
_acceptTask.Dispose();
_acceptTask = null;
return false;
}
}
}
private static TcpListener _listener;
private static Task _acceptTask;
private TcpClient _client;
public StaticDataConnection()
{
if (_listener == null)
{
_listener = new TcpListener(IPAddress.Any, FtpServer.Instance.Configuration.Server.ForceDataPort);
_listener.Start();
}
IsTslProtected = false;
}
public void AcceptClient()
{
if (_acceptTask?.IsCompleted == false)
{
_acceptTask.Wait(Timeout);
_acceptTask.Dispose();
_acceptTask = null;
}
_acceptTask = _listener.AcceptTcpClientAsync().ContinueWith(t =>
{
_client = t.Result;
if (IsTslProtected)
{
var sslStream = new SslStream(_client.GetStream(), false);
sslStream.AuthenticateAsServer(FtpServer.Instance.Configuration.Tls.X509Certificate, false, true);
Stream = sslStream;
}
else
{
Stream = _client.GetStream();
}
});
}
public void ActivateTls()
{
IsTslProtected = true;
}
public void Close()
{
Stream.Close();
_client.Close();
}
public void Create()
{
// Nothing to create as the TcpListener is shared by all
}
public void DesactivateTls()
{
IsTslProtected = false;
}
public static void Stop()
{
_listener?.Stop();
}
}
}

View File

@@ -46,6 +46,7 @@ namespace DearFTP
{ {
_isRunning = false; _isRunning = false;
_listener.Stop(); _listener.Stop();
StaticDataConnection.Stop();
} }
private void TcpLoop() private void TcpLoop()