mirror of
https://github.com/PepperDash/PepperDashCore.git
synced 2026-02-16 05:04:48 +00:00
Cleans up the disconnect logic and adds KillClient() to better control process of disposing of resources before reconnect attempts. Adds XML help for propeties and methods
This commit is contained in:
@@ -175,7 +175,6 @@ namespace PepperDash.Core
|
|||||||
{
|
{
|
||||||
Debug.Console(1, this, "Program stopping. Closing connection");
|
Debug.Console(1, this, "Program stopping. Closing connection");
|
||||||
Disconnect();
|
Disconnect();
|
||||||
//Client.Dispose();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -184,87 +183,86 @@ namespace PepperDash.Core
|
|||||||
/// Connect to the server, using the provided properties.
|
/// Connect to the server, using the provided properties.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public void Connect()
|
public void Connect()
|
||||||
{
|
{
|
||||||
ConnectEnabled = true;
|
ConnectEnabled = true;
|
||||||
Debug.Console(1, this, "attempting connect");
|
Debug.Console(1, this, "attempting connect");
|
||||||
|
|
||||||
// Cancel reconnect if running.
|
|
||||||
if (ReconnectTimer != null)
|
|
||||||
{
|
|
||||||
ReconnectTimer.Stop();
|
|
||||||
ReconnectTimer = null;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Don't try to connect if already
|
// Cancel reconnect if running.
|
||||||
if (IsConnected)
|
if (ReconnectTimer != null)
|
||||||
return;
|
{
|
||||||
|
ReconnectTimer.Stop();
|
||||||
// Don't go unless everything is here
|
ReconnectTimer = null;
|
||||||
if (string.IsNullOrEmpty(Hostname) || Port < 1 || Port > 65535
|
}
|
||||||
|| Username == null || Password == null)
|
|
||||||
{
|
|
||||||
Debug.Console(1, this, "Connect failed. Check hostname, port, username and password are set or not null");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (Client != null)
|
// Don't try to connect if already
|
||||||
{
|
if (IsConnected)
|
||||||
Debug.Console(1, this, "Cleaning up disconnected client");
|
return;
|
||||||
Client.ErrorOccurred -= Client_ErrorOccurred;
|
|
||||||
KillStream();
|
|
||||||
Client.Disconnect();
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
// This handles both password and keyboard-interactive (like on OS-X, 'nixes)
|
|
||||||
KeyboardInteractiveAuthenticationMethod kauth = new KeyboardInteractiveAuthenticationMethod(Username);
|
|
||||||
kauth.AuthenticationPrompt += new EventHandler<AuthenticationPromptEventArgs>(kauth_AuthenticationPrompt);
|
|
||||||
PasswordAuthenticationMethod pauth = new PasswordAuthenticationMethod(Username, Password);
|
|
||||||
Debug.Console(1, this, "Creating new SshClient");
|
|
||||||
ConnectionInfo connectionInfo = new ConnectionInfo(Hostname, Port, Username, pauth, kauth);
|
|
||||||
Client = new SshClient(connectionInfo);
|
|
||||||
}
|
|
||||||
|
|
||||||
Client.ErrorOccurred -= Client_ErrorOccurred;
|
// Don't go unless everything is here
|
||||||
Client.ErrorOccurred += Client_ErrorOccurred;
|
if (string.IsNullOrEmpty(Hostname) || Port < 1 || Port > 65535
|
||||||
|
|| Username == null || Password == null)
|
||||||
|
{
|
||||||
|
Debug.Console(1, this, "Connect failed. Check hostname, port, username and password are set or not null");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
//You can do it!
|
// Cleanup the old client if it already exists
|
||||||
ClientStatus = SocketStatus.SOCKET_STATUS_WAITING;
|
if (Client != null)
|
||||||
try
|
{
|
||||||
{
|
Debug.Console(1, this, "Cleaning up disconnected client");
|
||||||
Client.Connect();
|
Client.ErrorOccurred -= Client_ErrorOccurred;
|
||||||
TheStream = Client.CreateShellStream("PDTShell", 100, 80, 100, 200, 65534);
|
KillClient(SocketStatus.SOCKET_STATUS_BROKEN_LOCALLY);
|
||||||
TheStream.DataReceived += Stream_DataReceived;
|
}
|
||||||
//TheStream.ErrorOccurred += TheStream_ErrorOccurred;
|
|
||||||
Debug.Console(1, this, "Connected");
|
// This handles both password and keyboard-interactive (like on OS-X, 'nixes)
|
||||||
ClientStatus = SocketStatus.SOCKET_STATUS_CONNECTED;
|
KeyboardInteractiveAuthenticationMethod kauth = new KeyboardInteractiveAuthenticationMethod(Username);
|
||||||
return; // Success will not pass here
|
kauth.AuthenticationPrompt += new EventHandler<AuthenticationPromptEventArgs>(kauth_AuthenticationPrompt);
|
||||||
}
|
PasswordAuthenticationMethod pauth = new PasswordAuthenticationMethod(Username, Password);
|
||||||
catch (SshConnectionException e)
|
|
||||||
{
|
Debug.Console(1, this, "Creating new SshClient");
|
||||||
var ie = e.InnerException; // The details are inside!!
|
ConnectionInfo connectionInfo = new ConnectionInfo(Hostname, Port, Username, pauth, kauth);
|
||||||
if (ie is SocketException)
|
Client = new SshClient(connectionInfo);
|
||||||
Debug.Console(1, this, "'{0}' CONNECTION failure: Cannot reach host, ({1})", Key, ie.GetType());
|
|
||||||
else if (ie is System.Net.Sockets.SocketException)
|
Client.ErrorOccurred -= Client_ErrorOccurred;
|
||||||
Debug.Console(1, this, "'{0}' Connection failure: Cannot reach host '{1}' on port {2}, ({3})",
|
Client.ErrorOccurred += Client_ErrorOccurred;
|
||||||
Key, Hostname, Port, ie.GetType());
|
|
||||||
else if (ie is SshAuthenticationException)
|
//Attempt to connect
|
||||||
{
|
ClientStatus = SocketStatus.SOCKET_STATUS_WAITING;
|
||||||
Debug.Console(1, this, "Authentication failure for username '{0}', ({1})",
|
try
|
||||||
Username, ie.GetType());
|
{
|
||||||
}
|
Client.Connect();
|
||||||
else
|
TheStream = Client.CreateShellStream("PDTShell", 100, 80, 100, 200, 65534);
|
||||||
Debug.Console(1, this, "Error on connect:\r({0})", e);
|
TheStream.DataReceived += Stream_DataReceived;
|
||||||
}
|
//TheStream.ErrorOccurred += TheStream_ErrorOccurred;
|
||||||
catch (Exception e)
|
Debug.Console(1, this, "Connected");
|
||||||
{
|
ClientStatus = SocketStatus.SOCKET_STATUS_CONNECTED;
|
||||||
Debug.Console(1, this, "Unhandled exception on connect:\r({0})", e);
|
return; // Success will not pass here
|
||||||
}
|
}
|
||||||
|
catch (SshConnectionException e)
|
||||||
// Sucess will not make it this far
|
{
|
||||||
ClientStatus = SocketStatus.SOCKET_STATUS_CONNECT_FAILED;
|
var ie = e.InnerException; // The details are inside!!
|
||||||
HandleConnectionFailure();
|
if (ie is SocketException)
|
||||||
}
|
Debug.Console(1, this, "'{0}' CONNECTION failure: Cannot reach host, ({1})", Key, ie.GetType());
|
||||||
|
else if (ie is System.Net.Sockets.SocketException)
|
||||||
|
Debug.Console(1, this, "'{0}' Connection failure: Cannot reach host '{1}' on port {2}, ({3})",
|
||||||
|
Key, Hostname, Port, ie.GetType());
|
||||||
|
else if (ie is SshAuthenticationException)
|
||||||
|
{
|
||||||
|
Debug.Console(1, this, "Authentication failure for username '{0}', ({1})",
|
||||||
|
Username, ie.GetType());
|
||||||
|
}
|
||||||
|
else
|
||||||
|
Debug.Console(1, this, "Error on connect:\r({0})", e);
|
||||||
|
}
|
||||||
|
catch (Exception e)
|
||||||
|
{
|
||||||
|
Debug.Console(1, this, "Unhandled exception on connect:\r({0})", e);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Sucess will not make it this far
|
||||||
|
ClientStatus = SocketStatus.SOCKET_STATUS_CONNECT_FAILED;
|
||||||
|
HandleConnectionFailure();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@@ -281,28 +279,32 @@ namespace PepperDash.Core
|
|||||||
ReconnectTimer = null;
|
ReconnectTimer = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
KillStream();
|
KillClient(SocketStatus.SOCKET_STATUS_BROKEN_LOCALLY);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Kills the stream, cleans up the client and sets it to null
|
||||||
|
/// </summary>
|
||||||
|
private void KillClient(SocketStatus status)
|
||||||
|
{
|
||||||
|
KillStream();
|
||||||
|
|
||||||
if (Client != null)
|
if (Client != null)
|
||||||
{
|
{
|
||||||
Client.Disconnect();
|
Client.Disconnect();
|
||||||
Client = null;
|
Client = null;
|
||||||
ClientStatus = SocketStatus.SOCKET_STATUS_BROKEN_LOCALLY;
|
ClientStatus = status;
|
||||||
Debug.Console(1, this, "Disconnected");
|
Debug.Console(1, this, "Disconnected");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Anything to do with reestablishing connection on failures
|
/// Anything to do with reestablishing connection on failures
|
||||||
/// </summary>
|
/// </summary>
|
||||||
void HandleConnectionFailure()
|
void HandleConnectionFailure()
|
||||||
{
|
{
|
||||||
if (Client != null)
|
KillClient(SocketStatus.SOCKET_STATUS_CONNECT_FAILED);
|
||||||
{
|
|
||||||
Client.Disconnect();
|
|
||||||
Client = null;
|
|
||||||
}
|
|
||||||
KillStream();
|
|
||||||
Debug.Console(2, this, "Client nulled due to connection failure. AutoReconnect: {0}, ConnectEnabled: {1}", AutoReconnect, ConnectEnabled);
|
Debug.Console(2, this, "Client nulled due to connection failure. AutoReconnect: {0}, ConnectEnabled: {1}", AutoReconnect, ConnectEnabled);
|
||||||
|
|
||||||
if (AutoReconnect && ConnectEnabled)
|
if (AutoReconnect && ConnectEnabled)
|
||||||
@@ -327,24 +329,20 @@ namespace PepperDash.Core
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Kills the stream
|
||||||
|
/// </summary>
|
||||||
void KillStream()
|
void KillStream()
|
||||||
{
|
{
|
||||||
if (TheStream != null)
|
if (TheStream != null)
|
||||||
{
|
{
|
||||||
TheStream.DataReceived -= Stream_DataReceived;
|
TheStream.DataReceived -= Stream_DataReceived;
|
||||||
//TheStream.ErrorOccurred -= TheStream_ErrorOccurred;
|
|
||||||
TheStream.Close();
|
TheStream.Close();
|
||||||
TheStream.Dispose();
|
TheStream.Dispose();
|
||||||
TheStream = null;
|
TheStream = null;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
//bool PropertiesHaveChanged()
|
|
||||||
//{
|
|
||||||
// return Hostname != PreviousHostname || Port != PreviousPort
|
|
||||||
// || Username != PreviousUsername || Password != PreviousPassword;
|
|
||||||
//}
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Handles the keyboard interactive authentication, should it be required.
|
/// Handles the keyboard interactive authentication, should it be required.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
@@ -375,17 +373,6 @@ namespace PepperDash.Core
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
///// <summary>
|
|
||||||
///// Handler for errors on the stream...
|
|
||||||
///// </summary>
|
|
||||||
///// <param name="sender"></param>
|
|
||||||
///// <param name="e"></param>
|
|
||||||
//void TheStream_ErrorOccurred(object sender, ExceptionEventArgs e)
|
|
||||||
//{
|
|
||||||
// Debug.Console(1, this, "Unhandled SSH STREAM error: {0}", e.Exception);
|
|
||||||
// ClientStatus = SocketStatus.SOCKET_STATUS_BROKEN_REMOTELY;
|
|
||||||
// HandleConnectionFailure();
|
|
||||||
//}
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Error event handler for client events - disconnect, etc. Will forward those events via ConnectionChange
|
/// Error event handler for client events - disconnect, etc. Will forward those events via ConnectionChange
|
||||||
@@ -414,7 +401,7 @@ namespace PepperDash.Core
|
|||||||
#region IBasicCommunication Members
|
#region IBasicCommunication Members
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
///
|
/// Sends text to the server
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="text"></param>
|
/// <param name="text"></param>
|
||||||
public void SendText(string text)
|
public void SendText(string text)
|
||||||
@@ -435,6 +422,10 @@ namespace PepperDash.Core
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Sends Bytes to the server
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="bytes"></param>
|
||||||
public void SendBytes(byte[] bytes)
|
public void SendBytes(byte[] bytes)
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
@@ -463,16 +454,36 @@ namespace PepperDash.Core
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
public class SshConnectionChangeEventArgs : EventArgs
|
public class SshConnectionChangeEventArgs : EventArgs
|
||||||
{
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Connection State
|
||||||
|
/// </summary>
|
||||||
public bool IsConnected { get; private set; }
|
public bool IsConnected { get; private set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Connection Status represented as a ushort
|
||||||
|
/// </summary>
|
||||||
public ushort UIsConnected { get { return (ushort)(Client.IsConnected ? 1 : 0); } }
|
public ushort UIsConnected { get { return (ushort)(Client.IsConnected ? 1 : 0); } }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// The client
|
||||||
|
/// </summary>
|
||||||
public GenericSshClient Client { get; private set; }
|
public GenericSshClient Client { get; private set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Socket Status as represented by
|
||||||
|
/// </summary>
|
||||||
public ushort Status { get { return Client.UStatus; } }
|
public ushort Status { get { return Client.UStatus; } }
|
||||||
|
|
||||||
// S+ Constructor
|
/// <summary>
|
||||||
|
/// S+ Constructor
|
||||||
|
/// </summary>
|
||||||
public SshConnectionChangeEventArgs() { }
|
public SshConnectionChangeEventArgs() { }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// EventArgs class
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="isConnected">Connection State</param>
|
||||||
|
/// <param name="client">The Client</param>
|
||||||
public SshConnectionChangeEventArgs(bool isConnected, GenericSshClient client)
|
public SshConnectionChangeEventArgs(bool isConnected, GenericSshClient client)
|
||||||
{
|
{
|
||||||
IsConnected = isConnected;
|
IsConnected = isConnected;
|
||||||
|
|||||||
Reference in New Issue
Block a user