Skip to content

Commit 2f6c1ca

Browse files
committed
Two new features for connections
More obsoleted properties/functions
1 parent fa19c78 commit 2f6c1ca

10 files changed

Lines changed: 216 additions & 69 deletions

File tree

src/FubarDev.FtpServer.Abstractions/ConnectionExtensions.cs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
55
using System;
66
using System.Net.Sockets;
77
using System.Threading.Tasks;
8-
8+
using FubarDev.FtpServer.Features;
99
using JetBrains.Annotations;
1010

1111
namespace FubarDev.FtpServer
@@ -46,7 +46,7 @@ public static async Task<IFtpResponse> SendResponseAsync(
4646
finally
4747
{
4848
responseSocket.Dispose();
49-
connection.Data.PassiveSocketClient = null;
49+
connection.Features.Get<ISecureConnectionFeature>().PassiveSocketClient = null;
5050
}
5151
}
5252
}
Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
// <copyright file="IConnectionFeature.cs" company="Fubar Development Junker">
2+
// Copyright (c) Fubar Development Junker. All rights reserved.
3+
// </copyright>
4+
5+
using System.Net;
6+
using JetBrains.Annotations;
7+
8+
namespace FubarDev.FtpServer.Features
9+
{
10+
public interface IConnectionFeature
11+
{
12+
/// <summary>
13+
/// Gets the local end point.
14+
/// </summary>
15+
[NotNull]
16+
IPEndPoint LocalEndPoint { get; }
17+
18+
/// <summary>
19+
/// Gets the remote address of the client.
20+
/// </summary>
21+
[NotNull]
22+
Address RemoteAddress { get; }
23+
}
24+
}
Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
// <copyright file="ISecureConnectionFeature.cs" company="Fubar Development Junker">
2+
// Copyright (c) Fubar Development Junker. All rights reserved.
3+
// </copyright>
4+
5+
using System.IO;
6+
using System.Net.Sockets;
7+
using JetBrains.Annotations;
8+
9+
namespace FubarDev.FtpServer.Features
10+
{
11+
public interface ISecureConnectionFeature
12+
{
13+
/// <summary>
14+
/// Gets the control connection stream.
15+
/// </summary>
16+
[NotNull]
17+
Stream OriginalStream { get; }
18+
19+
/// <summary>
20+
/// Gets or sets the control connection stream.
21+
/// </summary>
22+
[NotNull]
23+
Stream SocketStream { get; set; }
24+
25+
/// <summary>
26+
/// Gets a value indicating whether this is a secure connection.
27+
/// </summary>
28+
bool IsSecure { get; }
29+
30+
/// <summary>
31+
/// Gets or sets the data connection for a passive data transfer.
32+
/// </summary>
33+
[CanBeNull]
34+
TcpClient PassiveSocketClient { get; set; }
35+
36+
/// <summary>
37+
/// Gets or sets a delegate that allows the creation of an encrypted stream.
38+
/// </summary>
39+
[CanBeNull]
40+
CreateEncryptedStreamDelegate CreateEncryptedStream { get; set; }
41+
}
42+
}

src/FubarDev.FtpServer.Abstractions/FtpConnectionData.cs

Lines changed: 21 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -145,7 +145,12 @@ public Address PortAddress
145145
/// Gets or sets the data connection for a passive data transfer.
146146
/// </summary>
147147
[CanBeNull]
148-
public TcpClient PassiveSocketClient { get; set; }
148+
[Obsolete("Query the information using the ISecureConnectionFeature instead.")]
149+
public TcpClient PassiveSocketClient
150+
{
151+
get => _featureCollection.Get<ISecureConnectionFeature>().PassiveSocketClient;
152+
set => _featureCollection.Get<ISecureConnectionFeature>().PassiveSocketClient = value;
153+
}
149154

150155
/// <summary>
151156
/// Gets the <see cref="BackgroundCommandHandler"/> that's required for the <c>ABOR</c> command.
@@ -206,7 +211,7 @@ public SearchResult<IUnixFileSystemEntry> RenameFrom
206211
{
207212
if (feature == null)
208213
{
209-
feature = new RenameCommandFeature();
214+
feature = new RenameCommandFeature(value);
210215
_featureCollection.Set(feature);
211216
}
212217

@@ -230,7 +235,12 @@ public SearchResult<IUnixFileSystemEntry> RenameFrom
230235
/// Gets or sets a delegate that allows the creation of an encrypted stream.
231236
/// </summary>
232237
[CanBeNull]
233-
public CreateEncryptedStreamDelegate CreateEncryptedStream { get; set; }
238+
[Obsolete("Query the information using the ISecureConnectionFeature instead.")]
239+
public CreateEncryptedStreamDelegate CreateEncryptedStream
240+
{
241+
get => _featureCollection.Get<ISecureConnectionFeature>().CreateEncryptedStream;
242+
set => _featureCollection.Get<ISecureConnectionFeature>().CreateEncryptedStream = value;
243+
}
234244

235245
/// <summary>
236246
/// Gets or sets user data as <c>dynamic</c> object.
@@ -241,9 +251,10 @@ public SearchResult<IUnixFileSystemEntry> RenameFrom
241251
/// <inheritdoc/>
242252
public void Dispose()
243253
{
244-
PassiveSocketClient?.Dispose();
254+
var secureConnectionFeature = _featureCollection.Get<ISecureConnectionFeature>();
255+
secureConnectionFeature.PassiveSocketClient?.Dispose();
245256
(_featureCollection.Get<IFileSystemFeature>() as IDisposable)?.Dispose();
246-
PassiveSocketClient = null;
257+
secureConnectionFeature.PassiveSocketClient = null;
247258
}
248259

249260
/// <summary>
@@ -260,6 +271,11 @@ private class RestCommandFeature : IRestCommandFeature
260271
/// </summary>
261272
private class RenameCommandFeature : IRenameCommandFeature
262273
{
274+
public RenameCommandFeature(SearchResult<IUnixFileSystemEntry> renameFrom)
275+
{
276+
RenameFrom = renameFrom;
277+
}
278+
263279
/// <inheritdoc />
264280
public SearchResult<IUnixFileSystemEntry> RenameFrom { get; set; }
265281
}

src/FubarDev.FtpServer.Abstractions/IFtpConnection.cs

Lines changed: 5 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@
1313
using System.Text;
1414
using System.Threading;
1515
using System.Threading.Tasks;
16-
16+
using FubarDev.FtpServer.Features;
1717
using JetBrains.Annotations;
1818

1919
using Microsoft.AspNetCore.Http.Features;
@@ -24,7 +24,7 @@ namespace FubarDev.FtpServer
2424
/// <summary>
2525
/// The interface for an FTP connection.
2626
/// </summary>
27-
public interface IFtpConnection : IDisposable
27+
public interface IFtpConnection : IConnectionFeature, IDisposable
2828
{
2929
/// <summary>
3030
/// Gets or sets the event handler that is triggered when the connection is closed.
@@ -62,35 +62,26 @@ public interface IFtpConnection : IDisposable
6262
[CanBeNull]
6363
ILogger Log { get; }
6464

65-
/// <summary>
66-
/// Gets the local end point.
67-
/// </summary>
68-
[NotNull]
69-
IPEndPoint LocalEndPoint { get; }
70-
7165
/// <summary>
7266
/// Gets the control connection stream.
7367
/// </summary>
7468
[NotNull]
69+
[Obsolete("Query the information using the ISecureConnectionFeature instead.")]
7570
Stream OriginalStream { get; }
7671

7772
/// <summary>
7873
/// Gets or sets the control connection stream.
7974
/// </summary>
8075
[NotNull]
76+
[Obsolete("Query the information using the ISecureConnectionFeature instead.")]
8177
Stream SocketStream { get; set; }
8278

8379
/// <summary>
8480
/// Gets a value indicating whether this is a secure connection.
8581
/// </summary>
82+
[Obsolete("Query the information using the ISecureConnectionFeature instead.")]
8683
bool IsSecure { get; }
8784

88-
/// <summary>
89-
/// Gets the remote address of the client.
90-
/// </summary>
91-
[NotNull]
92-
Address RemoteAddress { get; }
93-
9485
/// <summary>
9586
/// Gets the cancellation token to use to signal a task cancellation.
9687
/// </summary>

src/FubarDev.FtpServer.Commands/CommandHandlers/PasvCommandHandler.cs

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -52,11 +52,12 @@ public PasvCommandHandler(
5252
public override async Task<IFtpResponse> Process(FtpCommand command, CancellationToken cancellationToken)
5353
{
5454
var transferFeature = Connection.Features.Get<ITransferConfigurationFeature>();
55+
var secureConnectionFeature = Connection.Features.Get<ISecureConnectionFeature>();
5556

56-
if (Data.PassiveSocketClient != null)
57+
if (secureConnectionFeature.PassiveSocketClient != null)
5758
{
58-
Data.PassiveSocketClient.Dispose();
59-
Data.PassiveSocketClient = null;
59+
secureConnectionFeature.PassiveSocketClient.Dispose();
60+
secureConnectionFeature.PassiveSocketClient = null;
6061
}
6162

6263
if (transferFeature.TransferTypeCommandUsed != null && !string.Equals(
@@ -132,7 +133,7 @@ await Connection.WriteAsync(
132133
Connection.Log?.LogDebug($"Data connection accepted from {pasvRemoteAddress}");
133134
}
134135

135-
Data.PassiveSocketClient = passiveClient;
136+
secureConnectionFeature.PassiveSocketClient = passiveClient;
136137
}
137138
}
138139
}

src/FubarDev.FtpServer.Commands/CommandHandlers/QuitCommandHandler.cs

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99
using System.Threading.Tasks;
1010

1111
using FubarDev.FtpServer.Commands;
12+
using FubarDev.FtpServer.Features;
1213

1314
namespace FubarDev.FtpServer.CommandHandlers
1415
{
@@ -26,7 +27,8 @@ public override Task<IFtpResponse> Process(FtpCommand command, CancellationToken
2627
{
2728
AfterWriteAction = async (conn, ct) =>
2829
{
29-
await conn.SocketStream.FlushAsync(ct)
30+
var secureConnectionFeature = conn.Features.Get<ISecureConnectionFeature>();
31+
await secureConnectionFeature.SocketStream.FlushAsync(ct)
3032
.ConfigureAwait(false);
3133
conn.Close();
3234
},

src/FubarDev.FtpServer.Commands/CommandHandlers/ReinCommandHandler.cs

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@
66
using System.Threading.Tasks;
77

88
using FubarDev.FtpServer.Commands;
9-
9+
using FubarDev.FtpServer.Features;
1010
using JetBrains.Annotations;
1111

1212
using Microsoft.Extensions.DependencyInjection;
@@ -25,12 +25,13 @@ public override async Task<IFtpResponse> Process(FtpCommand command, Cancellatio
2525
var loginStateMachine = Connection.ConnectionServices.GetRequiredService<IFtpLoginStateMachine>();
2626
loginStateMachine.Reset();
2727

28-
if (Connection.SocketStream != Connection.OriginalStream)
28+
var secureConnectionFeature = Connection.Features.Get<ISecureConnectionFeature>();
29+
if (secureConnectionFeature.SocketStream != secureConnectionFeature.OriginalStream)
2930
{
30-
await Connection.SocketStream.FlushAsync(cancellationToken)
31+
await secureConnectionFeature.SocketStream.FlushAsync(cancellationToken)
3132
.ConfigureAwait(false);
32-
Connection.SocketStream.Dispose();
33-
Connection.SocketStream = Connection.OriginalStream;
33+
secureConnectionFeature.SocketStream.Dispose();
34+
secureConnectionFeature.SocketStream = secureConnectionFeature.OriginalStream;
3435
}
3536

3637
return new FtpResponse(220, T("FTP Server Ready"));

src/FubarDev.FtpServer/Authentication/TlsAuthenticationMechanism.cs

Lines changed: 10 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88
using System.Security.Cryptography.X509Certificates;
99
using System.Threading;
1010
using System.Threading.Tasks;
11-
11+
using FubarDev.FtpServer.Features;
1212
using JetBrains.Annotations;
1313

1414
using Microsoft.Extensions.Logging;
@@ -71,24 +71,25 @@ public override Task<IFtpResponse> HandleAuthAsync(string methodIdentifier, Canc
7171
{
7272
AfterWriteAction = async (conn, ct) =>
7373
{
74-
await conn.SocketStream.FlushAsync(ct).ConfigureAwait(false);
74+
var secureConnectionFeature = conn.Features.Get<ISecureConnectionFeature>();
75+
await secureConnectionFeature.SocketStream.FlushAsync(ct).ConfigureAwait(false);
7576

7677
try
7778
{
7879
var sslStream = await _sslStreamWrapperFactory.WrapStreamAsync(
79-
conn.OriginalStream,
80+
secureConnectionFeature.OriginalStream,
8081
true,
8182
_serverCertificate,
8283
cancellationToken)
8384
.ConfigureAwait(false);
84-
if (conn.SocketStream != conn.OriginalStream)
85+
if (secureConnectionFeature.SocketStream != secureConnectionFeature.OriginalStream)
8586
{
8687
// Close old SSL connection.
87-
await _sslStreamWrapperFactory.CloseStreamAsync(conn.SocketStream, cancellationToken)
88+
await _sslStreamWrapperFactory.CloseStreamAsync(secureConnectionFeature.SocketStream, cancellationToken)
8889
.ConfigureAwait(false);
8990
}
9091

91-
conn.SocketStream = sslStream;
92+
secureConnectionFeature.SocketStream = sslStream;
9293
}
9394
catch (Exception ex)
9495
{
@@ -123,13 +124,14 @@ public override Task<IFtpResponse> HandlePbszAsync(long size, CancellationToken
123124
/// <inheritdoc />
124125
public override Task<IFtpResponse> HandleProtAsync(string protCode, CancellationToken cancellationToken)
125126
{
127+
var secureConnectionFeature = Connection.Features.Get<ISecureConnectionFeature>();
126128
switch (protCode.ToUpperInvariant())
127129
{
128130
case "C":
129-
Connection.Data.CreateEncryptedStream = null;
131+
secureConnectionFeature.CreateEncryptedStream = null;
130132
break;
131133
case "P":
132-
Connection.Data.CreateEncryptedStream = CreateSslStream;
134+
secureConnectionFeature.CreateEncryptedStream = CreateSslStream;
133135
break;
134136
default:
135137
return Task.FromResult<IFtpResponse>(new FtpResponse(SecurityActionResult.RequestedProtLevelNotSupported, T("A data channel protection level other than C, or P is not supported.")));

0 commit comments

Comments
 (0)