diff --git a/Renci.SshClient/Renci.SshClient.Tests/ConnectionData.cs b/Renci.SshClient/Renci.SshClient.Tests/ConnectionData.cs index 96930cbd..0e7b0c9b 100644 --- a/Renci.SshClient/Renci.SshClient.Tests/ConnectionData.cs +++ b/Renci.SshClient/Renci.SshClient.Tests/ConnectionData.cs @@ -3,13 +3,13 @@ namespace Renci.SshClient.Tests { public static class ConnectionData { - public static string Host { get { return "152.54.8.155"; } } + public static string Host { get { return "oleg-centos.edc.renci.org"; } } public static int Port { get { return 22; } } - public static string Username { get { return "oleg"; } } + public static string Username { get { return "tester"; } } - public static string Password { get { return "Maya2kap#"; } } + public static string Password { get { return "tester"; } } public static string RsaKeyFilePath { get { return @"RSA key path"; } } diff --git a/Renci.SshClient/Renci.SshClient/Common/ConnectingEventArgs.cs b/Renci.SshClient/Renci.SshClient/Common/ConnectingEventArgs.cs new file mode 100644 index 00000000..5ab8b178 --- /dev/null +++ b/Renci.SshClient/Renci.SshClient/Common/ConnectingEventArgs.cs @@ -0,0 +1,54 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; + +namespace Renci.SshClient.Common +{ + public class ConnectingEventArgs : EventArgs + { + public IDictionary KeyExchangeAlgorithms { get; private set; } + + public IDictionary Encryptions { get; private set; } + + public IDictionary HmacAlgorithms { get; private set; } + + public IDictionary HostKeyAlgorithms { get; private set; } + + public IDictionary SupportedAuthenticationMethods { get; private set; } + + public IDictionary CompressionAlgorithms { get; private set; } + + public string Host { get; set; } + + public int Port { get; set; } + + public string Username { get; set; } + + public string Password { get; set; } + + public PrivateKeyFile KeyFile { get; set; } + + public TimeSpan Timeout { get; set; } + + public int RetryAttempts { get; set; } + + public int MaxSessions { get; set; } + + public ConnectingEventArgs( + IDictionary keyExchangeAlgorithms, + IDictionary encryptions, + IDictionary hmacAlgorithms, + IDictionary hostKeyAlgorithms, + IDictionary supportedAuthenticationMethods, + IDictionary compressionAlgorithms) + { + this.KeyExchangeAlgorithms = keyExchangeAlgorithms; + this.Encryptions = encryptions; + this.HmacAlgorithms = hmacAlgorithms; + this.HostKeyAlgorithms = hostKeyAlgorithms; + this.SupportedAuthenticationMethods = supportedAuthenticationMethods; + this.CompressionAlgorithms = compressionAlgorithms; + } + } +} diff --git a/Renci.SshClient/Renci.SshClient/Renci.SshClient.csproj b/Renci.SshClient/Renci.SshClient/Renci.SshClient.csproj index 63e8d89e..50f681ce 100644 --- a/Renci.SshClient/Renci.SshClient/Renci.SshClient.csproj +++ b/Renci.SshClient/Renci.SshClient/Renci.SshClient.csproj @@ -64,6 +64,7 @@ + diff --git a/Renci.SshClient/Renci.SshClient/Session.cs b/Renci.SshClient/Renci.SshClient/Session.cs index c577090d..55510170 100644 --- a/Renci.SshClient/Renci.SshClient/Session.cs +++ b/Renci.SshClient/Renci.SshClient/Session.cs @@ -220,7 +220,7 @@ namespace Renci.SshClient public event EventHandler ErrorOccured; - public event EventHandler Connecting; + public event EventHandler Connecting; public event EventHandler Connected; @@ -450,25 +450,49 @@ namespace Renci.SshClient if (this.IsConnected) return; - if (this.Connecting != null) - { - // TODO: Create custom ConnectingEventArgs to allow to pass different connection parameters - this.Connecting(this, new EventArgs()); - } - lock (this) { - // If connected dont connect again + // If connected don't connect again if (this.IsConnected) return; + var eventArgs = new ConnectingEventArgs(this.KeyExchangeAlgorithms, + this.Encryptions, + this.HmacAlgorithms, + this.HostKeyAlgorithms, + this.SupportedAuthenticationMethods, + this.CompressionAlgorithms); + // Populate event args connection information + eventArgs.Host = this.ConnectionInfo.Host; + eventArgs.Port = this.ConnectionInfo.Port; + eventArgs.Username = this.ConnectionInfo.Username; + eventArgs.Password = this.ConnectionInfo.Password; + eventArgs.KeyFile = this.ConnectionInfo.KeyFile; + eventArgs.Timeout = this.ConnectionInfo.Timeout; + eventArgs.RetryAttempts = this.ConnectionInfo.RetryAttempts; + eventArgs.MaxSessions = this.ConnectionInfo.MaxSessions; + + if (this.Connecting != null) + { + this.Connecting(this, eventArgs); + + // Update connection information if it was changed by event handler + this.ConnectionInfo.Host = eventArgs.Host; + this.ConnectionInfo.Port = eventArgs.Port; + this.ConnectionInfo.Username = eventArgs.Username; + this.ConnectionInfo.Password = eventArgs.Password; + this.ConnectionInfo.KeyFile = eventArgs.KeyFile; + this.ConnectionInfo.Timeout = eventArgs.Timeout; + this.ConnectionInfo.RetryAttempts = eventArgs.RetryAttempts; + } + var ep = new IPEndPoint(Dns.GetHostAddresses(this.ConnectionInfo.Host)[0], this.ConnectionInfo.Port); this._socket = new Socket(ep.AddressFamily, SocketType.Stream, ProtocolType.Tcp); // Connect socket with 5 seconds timeout var connectResult = this._socket.BeginConnect(ep, null, null); - connectResult.AsyncWaitHandle.WaitOne(this.ConnectionInfo.Timeout); + connectResult.AsyncWaitHandle.WaitOne(eventArgs.Timeout); this._socket.EndConnect(connectResult); @@ -554,7 +578,7 @@ namespace Renci.SshClient foreach (var methodName in this.SupportedAuthenticationMethods.Keys) { var userAuthentication = this.SupportedAuthenticationMethods[methodName].CreateInstance(); - + userAuthentication.Init(this); if (userAuthentication.Execute()) diff --git a/Renci.SshClient/Renci.SshClient/SshBaseClient.cs b/Renci.SshClient/Renci.SshClient/SshBaseClient.cs index f383d0e2..6ad6b549 100644 --- a/Renci.SshClient/Renci.SshClient/SshBaseClient.cs +++ b/Renci.SshClient/Renci.SshClient/SshBaseClient.cs @@ -5,6 +5,7 @@ using System.Text; using System.IO; using Renci.SshClient.Sftp; using Renci.SshClient.Security; +using Renci.SshClient.Common; namespace Renci.SshClient { @@ -37,6 +38,11 @@ namespace Renci.SshClient } } + /// + /// Occurs when client is about to connect to the server. + /// + public event EventHandler Connecting; + /// /// Initializes a new instance of the class. /// @@ -60,6 +66,7 @@ namespace Renci.SshClient } this.Session = new Session(this.ConnectionInfo); + this.Session.Connecting += Session_Connecting; this.Session.Connect(); this.OnConnected(); @@ -73,6 +80,7 @@ namespace Renci.SshClient this.OnDisconnecting(); this.Session.Disconnect(); + this.Session.Connecting -= Session_Connecting; this.OnDisconnected(); } @@ -117,6 +125,15 @@ namespace Renci.SshClient } + private void Session_Connecting(object sender, ConnectingEventArgs e) + { + if (this.Connecting != null) + { + this.Connecting(this, e); + } + } + + #region IDisposable Members private bool _isDisposed = false; diff --git a/Renci.SshClient/Renci.SshClient/SshCommand.cs b/Renci.SshClient/Renci.SshClient/SshCommand.cs index 372978df..e6107bb6 100644 --- a/Renci.SshClient/Renci.SshClient/SshCommand.cs +++ b/Renci.SshClient/Renci.SshClient/SshCommand.cs @@ -8,6 +8,7 @@ using Renci.SshClient.Common; using Renci.SshClient.Messages; using Renci.SshClient.Messages.Connection; using Renci.SshClient.Messages.Transport; +using System.Threading.Tasks; namespace Renci.SshClient { @@ -203,8 +204,8 @@ namespace Renci.SshClient this._asyncResult.IsCompleted = true; if (this._callback != null) { - // TODO: Execute this method on different thread since it will be run on message listener - this._callback(this._asyncResult); + // Execute callback on different thread + Task.Factory.StartNew(() => { this._callback(this._asyncResult); }); } ((EventWaitHandle)_asyncResult.AsyncWaitHandle).Set(); }