Skip to content

Commit 4963ba9

Browse files
committed
Improvements bases on feedback. Fixed tests. Added documentation.
1 parent d7e4e15 commit 4963ba9

File tree

117 files changed

+275
-45
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

117 files changed

+275
-45
lines changed

docfx/logging.md

Lines changed: 25 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,31 @@
11
Logging
22
=================
33

4-
SSH.NET uses the [Microsoft.Extensions.Logging](https://learn.microsoft.com/dotnet/core/extensions/logging) API to log diagnostic messages. In order to access the log messages of SSH.NET in your own application for diagnosis, register your own `ILoggerFactory` before using the SSH.NET APIs, for example:
4+
SSH.NET uses the [Microsoft.Extensions.Logging](https://learn.microsoft.com/dotnet/core/extensions/logging) API to log diagnostic messages.
5+
6+
It is possible to specify a logger in the `ConnectionInfo`, for example:
7+
8+
```cs
9+
using Microsoft.Extensions.Logging;
10+
11+
ILoggerFactory loggerFactory = LoggerFactory.Create(builder =>
12+
{
13+
builder.SetMinimumLevel(LogLevel.Debug);
14+
builder.AddConsole();
15+
});
16+
17+
var connectionInfo = new ConnectionInfo("sftp.foo.com",
18+
"guest",
19+
new PasswordAuthenticationMethod("guest", "pwd"));
20+
21+
connectionInfo.LoggerFactory = loggerFactory;
22+
using (var client = new SftpClient(connectionInfo))
23+
{
24+
client.Connect();
25+
}
26+
```
27+
28+
You can also register an application-wide `ILoggerFactory` before using the SSH.NET APIs, this will be used as a fallback if the `ConnectionInfo` is not set, for example:
529

630
```cs
731
using Microsoft.Extensions.Logging;

src/Renci.SshNet/BaseClient.cs

Lines changed: 6 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,8 @@ public abstract class BaseClient : IBaseClient
2020
/// Holds value indicating whether the connection info is owned by this client.
2121
/// </summary>
2222
private readonly bool _ownsConnectionInfo;
23+
24+
private readonly ILogger _logger;
2325
private readonly IServiceFactory _serviceFactory;
2426
private readonly object _keepAliveLock = new object();
2527
private TimeSpan _keepAliveInterval;
@@ -35,14 +37,6 @@ public abstract class BaseClient : IBaseClient
3537
/// </value>
3638
internal ISession? Session { get; private set; }
3739

38-
internal ILogger? Logger
39-
{
40-
get
41-
{
42-
return Session?.SessionLoggerFactory?.CreateLogger(GetType());
43-
}
44-
}
45-
4640
/// <summary>
4741
/// Gets the factory for creating new services.
4842
/// </summary>
@@ -198,6 +192,7 @@ private protected BaseClient(ConnectionInfo connectionInfo, bool ownsConnectionI
198192
_connectionInfo = connectionInfo;
199193
_ownsConnectionInfo = ownsConnectionInfo;
200194
_serviceFactory = serviceFactory;
195+
_logger = (connectionInfo.LoggerFactory ?? SshNetLoggingConfiguration.LoggerFactory).CreateLogger(GetType());
201196
_keepAliveInterval = Timeout.InfiniteTimeSpan;
202197
}
203198

@@ -351,7 +346,7 @@ public async Task ConnectAsync(CancellationToken cancellationToken)
351346
/// <exception cref="ObjectDisposedException">The method was called after the client was disposed.</exception>
352347
public void Disconnect()
353348
{
354-
Logger?.LogInformation("Disconnecting client.");
349+
_logger.LogInformation("Disconnecting client.");
355350

356351
CheckDisposed();
357352

@@ -450,7 +445,7 @@ protected virtual void Dispose(bool disposing)
450445

451446
if (disposing)
452447
{
453-
Logger?.LogDebug("Disposing client.");
448+
_logger.LogDebug("Disposing client.");
454449

455450
Disconnect();
456451

@@ -513,7 +508,7 @@ private void SendKeepAliveMessage()
513508
}
514509
catch (Exception ex)
515510
{
516-
Logger?.LogError(ex, "Error sending keepalive message");
511+
_logger.LogError(ex, "Error sending keepalive message");
517512
}
518513
finally
519514
{

src/Renci.SshNet/Connection/ConnectorBase.cs

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -15,15 +15,13 @@ namespace Renci.SshNet.Connection
1515
internal abstract class ConnectorBase : IConnector
1616
{
1717
private readonly ILogger _logger;
18-
private readonly ILoggerFactory _loggerFactory;
1918

2019
protected ConnectorBase(ISocketFactory socketFactory, ILoggerFactory loggerFactory)
2120
{
2221
ThrowHelper.ThrowIfNull(socketFactory);
2322

2423
SocketFactory = socketFactory;
25-
_loggerFactory = loggerFactory;
26-
_logger = _loggerFactory.CreateLogger(GetType());
24+
_logger = loggerFactory.CreateLogger(GetType());
2725
}
2826

2927
internal ISocketFactory SocketFactory { get; private set; }

src/Renci.SshNet/ForwardedPortDynamic.cs

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,6 @@ namespace Renci.SshNet
2121
/// </summary>
2222
public class ForwardedPortDynamic : ForwardedPort
2323
{
24-
private readonly ILogger _logger;
2524
private ForwardedPortStatus _status;
2625

2726
/// <summary>
@@ -75,7 +74,6 @@ public ForwardedPortDynamic(string host, uint port)
7574
BoundHost = host;
7675
BoundPort = port;
7776
_status = ForwardedPortStatus.Stopped;
78-
_logger = Session.SessionLoggerFactory.CreateLogger<ForwardedPortDynamic>();
7977
}
8078

8179
/// <summary>
@@ -416,7 +414,12 @@ private void InternalStop(TimeSpan timeout)
416414

417415
if (!_pendingChannelCountdown.Wait(timeout))
418416
{
419-
_logger.LogInformation("Timeout waiting for pending channels in dynamic forwarded port to close.");
417+
var session = Session;
418+
if (session != null)
419+
{
420+
var logger = session.SessionLoggerFactory.CreateLogger<ForwardedPortDynamic>();
421+
logger.LogInformation("Timeout waiting for pending channels in dynamic forwarded port to close.");
422+
}
420423
}
421424
}
422425

src/Renci.SshNet/ForwardedPortLocal.cs

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,6 @@ namespace Renci.SshNet
1414
/// </summary>
1515
public partial class ForwardedPortLocal : ForwardedPort
1616
{
17-
private readonly ILogger _logger;
1817
private ForwardedPortStatus _status;
1918
private bool _isDisposed;
2019
private Socket _listener;
@@ -103,7 +102,6 @@ public ForwardedPortLocal(string boundHost, uint boundPort, string host, uint po
103102
Host = host;
104103
Port = port;
105104
_status = ForwardedPortStatus.Stopped;
106-
_logger = Session.SessionLoggerFactory.CreateLogger<ForwardedPortLocal>();
107105
}
108106

109107
/// <summary>
@@ -390,7 +388,12 @@ private void InternalStop(TimeSpan timeout)
390388

391389
if (!_pendingChannelCountdown.Wait(timeout))
392390
{
393-
_logger.LogInformation("Timeout waiting for pending channels in local forwarded port to close.");
391+
var session = Session;
392+
if (session != null)
393+
{
394+
var logger = session.SessionLoggerFactory.CreateLogger<ForwardedPortLocal>();
395+
logger.LogInformation("Timeout waiting for pending channels in local forwarded port to close.");
396+
}
394397
}
395398
}
396399

src/Renci.SshNet/ForwardedPortRemote.cs

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,6 @@ namespace Renci.SshNet
1616
/// </summary>
1717
public class ForwardedPortRemote : ForwardedPort
1818
{
19-
private readonly ILogger _logger;
2019
private ForwardedPortStatus _status;
2120
private bool _requestStatus;
2221
private EventWaitHandle _globalRequestResponse = new AutoResetEvent(initialState: false);
@@ -100,7 +99,6 @@ public ForwardedPortRemote(IPAddress boundHostAddress, uint boundPort, IPAddress
10099
HostAddress = hostAddress;
101100
Port = port;
102101
_status = ForwardedPortStatus.Stopped;
103-
_logger = Session.SessionLoggerFactory.CreateLogger<ForwardedPortRemote>();
104102
}
105103

106104
/// <summary>
@@ -212,7 +210,12 @@ protected override void StopPort(TimeSpan timeout)
212210

213211
if (!_pendingChannelCountdown.Wait(timeout))
214212
{
215-
_logger.LogInformation("Timeout waiting for pending channels in remote forwarded port to close.");
213+
var session = Session;
214+
if (session != null)
215+
{
216+
var logger = session.SessionLoggerFactory.CreateLogger<ForwardedPortRemote>();
217+
logger.LogInformation("Timeout waiting for pending channels in remote forwarded port to close.");
218+
}
216219
}
217220

218221
_status = ForwardedPortStatus.Stopped;

src/Renci.SshNet/IConnectionInfo.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ internal interface IConnectionInfo
1818
/// Gets the logger factory for this connection.
1919
/// </summary>
2020
/// <value>
21-
/// The logger factory for this connection. If <see langword="null"/> then <see cref="SshNetLoggingConfiguration.LoggerFactory"/> should be used.
21+
/// The logger factory for this connection. If <see langword="null"/> then <see cref="SshNetLoggingConfiguration.LoggerFactory"/> is used.
2222
/// </value>
2323
public ILoggerFactory LoggerFactory { get; }
2424

src/Renci.SshNet/ISession.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,7 @@ internal interface ISession : IDisposable
2828
/// Gets the logger factory for this session.
2929
/// </summary>
3030
/// <value>
31-
/// The logger factory for this session.
31+
/// The logger factory for this session. Will never return <see langword="null"/>.
3232
/// </value>
3333
public ILoggerFactory SessionLoggerFactory { get; }
3434

src/Renci.SshNet/ISubsystemSession.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ internal interface ISubsystemSession : IDisposable
1616
/// Gets the logger factory for this subsystem session.
1717
/// </summary>
1818
/// <value>
19-
/// The logger factory for this connection.
19+
/// The logger factory for this connection. Will never return <see langword="null"/>.
2020
/// </value>
2121
public ILoggerFactory SessionLoggerFactory { get; }
2222

src/Renci.SshNet/Security/KeyExchange.cs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ namespace Renci.SshNet.Security
1818
/// </summary>
1919
public abstract class KeyExchange : Algorithm, IKeyExchange
2020
{
21-
private readonly ILogger _logger;
21+
private ILogger _logger;
2222
private Func<byte[], KeyHostAlgorithm> _hostKeyAlgorithmFactory;
2323
private CipherInfo _clientCipherInfo;
2424
private CipherInfo _serverCipherInfo;
@@ -69,13 +69,13 @@ public byte[] ExchangeHash
6969
/// </summary>
7070
protected KeyExchange()
7171
{
72-
_logger = Session.SessionLoggerFactory.CreateLogger(GetType());
7372
}
7473

7574
/// <inheritdoc/>
7675
public virtual void Start(Session session, KeyExchangeInitMessage message, bool sendClientInitMessage)
7776
{
7877
Session = session;
78+
_logger = Session.SessionLoggerFactory.CreateLogger(GetType());
7979

8080
if (sendClientInitMessage)
8181
{

0 commit comments

Comments
 (0)