diff --git a/Pepperdash Core/Pepperdash Core/Comm/GenericSshClient.cs b/Pepperdash Core/Pepperdash Core/Comm/GenericSshClient.cs index 947f778..afcbec4 100644 --- a/Pepperdash Core/Pepperdash Core/Comm/GenericSshClient.cs +++ b/Pepperdash Core/Pepperdash Core/Comm/GenericSshClient.cs @@ -26,7 +26,7 @@ namespace PepperDash.Core //***************************************************************************************************** //***************************************************************************************************** - public class GenericSshClient : Device, IBasicCommunication + public class GenericSshClient : Device, IBasicCommunication, IAutoReconnect { public event EventHandler BytesReceived; public event EventHandler TextReceived; @@ -66,12 +66,12 @@ namespace PepperDash.Core /// /// Millisecond value, determines the timeout period in between reconnect attempts /// - public ushort AutoReconnectIntervalMs { get; set; } + public int AutoReconnectIntervalMs { get; set; } SshClient Client; ShellStream TheStream; CTimer ReconnectTimer; - bool ReconnectTimerRunning; + //bool ReconnectTimerRunning; public GenericSshClient(string key, string hostname, int port, string username, string password) : base(key) @@ -82,6 +82,21 @@ namespace PepperDash.Core Port = port; Username = username; Password = password; + CrestronEnvironment.ProgramStatusEventHandler += new ProgramStatusEventHandler(CrestronEnvironment_ProgramStatusEventHandler); + } + + void CrestronEnvironment_ProgramStatusEventHandler(eProgramStatusEventType programEventType) + { + if (programEventType == eProgramStatusEventType.Stopping) + { + if (Client != null) + { + Debug.Console(2, this, "Closing connection"); + Client.Disconnect(); + Client.Dispose(); + Debug.Console(2, this, "Connection closed"); + } + } } /// @@ -89,59 +104,73 @@ namespace PepperDash.Core /// public void Connect() { - ReconnectTimerRunning = false; + Debug.Console(1, this, "attempting connect, IsConnected={0}", Client != null ? Client.IsConnected : false); + + //ReconnectTimerRunning = false; + if (ReconnectTimer != null) + { + ReconnectTimer.Stop(); + ReconnectTimer = null; + } + + if (IsConnected) + return; + if (Hostname != null && Hostname != string.Empty && Port > 0 && Username != null && Password != null) { - Debug.Console(1, this, "attempting connect, IsConnected={0}", IsConnected); - if (!IsConnected) - { - UStatus = 1; - IsConnected = false; - // This handles both password and keyboard-interactive (like on OS-X, 'nixes) - KeyboardInteractiveAuthenticationMethod kauth = new KeyboardInteractiveAuthenticationMethod(Username); - kauth.AuthenticationPrompt += new EventHandler(kauth_AuthenticationPrompt); - PasswordAuthenticationMethod pauth = new PasswordAuthenticationMethod(Username, Password); - ConnectionInfo connectionInfo = new ConnectionInfo(Hostname, Port, Username, pauth, kauth); - Client = new SshClient(connectionInfo); - Client.ErrorOccurred += Client_ErrorOccurred; - try + UStatus = 1; + IsConnected = false; + + // This handles both password and keyboard-interactive (like on OS-X, 'nixes) + KeyboardInteractiveAuthenticationMethod kauth = new KeyboardInteractiveAuthenticationMethod(Username); + kauth.AuthenticationPrompt += new EventHandler(kauth_AuthenticationPrompt); + PasswordAuthenticationMethod pauth = new PasswordAuthenticationMethod(Username, Password); + ConnectionInfo connectionInfo = new ConnectionInfo(Hostname, Port, Username, pauth, kauth); + // always spin up new client in case parameters have changed + if (Client != null) + { + Client.Disconnect(); + Client = null; + //Client.Dispose(); + } + Client = new SshClient(connectionInfo); + + Client.ErrorOccurred += Client_ErrorOccurred; + try + { + Client.Connect(); + if (Client.IsConnected) { - Client.Connect(); - if (Client.IsConnected) - { - Client.KeepAliveInterval = TimeSpan.FromSeconds(2); - Client.SendKeepAlive(); - IsConnected = true; - Debug.Console(1, this, "Connected"); - TheStream = Client.CreateShellStream("PDTShell", 100, 80, 100, 200, 65534); - TheStream.DataReceived += Stream_DataReceived; - //TheStream.ErrorOccurred += Stream_ErrorOccurred; - - } - return; - } - catch (SshConnectionException e) - { - var ie = e.InnerException; // The details are inside!! - string msg; - if (ie is SocketException) - msg = string.Format("'{0}' CONNECTION failure: Cannot reach host, ({1})", Key, ie.GetType()); - else if (ie is System.Net.Sockets.SocketException) - msg = string.Format("'{0}' Connection failure: Cannot reach host '{1}' on port {2}, ({3})", - Key, Hostname, Port, ie.GetType()); - else if (ie is SshAuthenticationException) - { - msg = string.Format("'{0}' Authentication failure for username '{1}', ({2})", - Username, Key, ie.GetType()); - Debug.Console(0, this, "Authentication failure for username '{0}', ({1})", - Username, ie.GetType()); - } - else - Debug.Console(0, this, "Error on connect:\r({0})", e); + Client.KeepAliveInterval = TimeSpan.FromSeconds(2); + Client.SendKeepAlive(); + IsConnected = true; + Debug.Console(1, this, "Connected"); + TheStream = Client.CreateShellStream("PDTShell", 100, 80, 100, 200, 65534); + TheStream.DataReceived += Stream_DataReceived; } + return; } + catch (SshConnectionException e) + { + var ie = e.InnerException; // The details are inside!! + string msg; + if (ie is SocketException) + msg = string.Format("'{0}' CONNECTION failure: Cannot reach host, ({1})", Key, ie.GetType()); + else if (ie is System.Net.Sockets.SocketException) + msg = string.Format("'{0}' Connection failure: Cannot reach host '{1}' on port {2}, ({3})", + Key, Hostname, Port, ie.GetType()); + else if (ie is SshAuthenticationException) + { + msg = string.Format("'{0}' Authentication failure for username '{1}', ({2})", + Username, Key, ie.GetType()); + Debug.Console(0, this, "Authentication failure for username '{0}', ({1})", + Username, ie.GetType()); + } + else + Debug.Console(0, this, "Error on connect:\r({0})", e); + } } else { @@ -160,7 +189,11 @@ namespace PepperDash.Core public void Disconnect() { // Stop trying reconnects, if we are - if(ReconnectTimer != null) ReconnectTimer.Stop(); + if (ReconnectTimer != null) + { + ReconnectTimer.Stop(); + ReconnectTimer = null; + } // Otherwise just close up if (Client != null) // && Client.IsConnected) <-- Doesn't always report properly... { @@ -181,10 +214,13 @@ namespace PepperDash.Core AutoReconnect, AutoReconnectIntervalMs); if (AutoReconnect) { - if (ReconnectTimer == null || !ReconnectTimerRunning) + if (ReconnectTimer == null)// || !ReconnectTimerRunning) { - ReconnectTimer = new CTimer(o => Connect(), AutoReconnectIntervalMs); - ReconnectTimerRunning = true; + ReconnectTimer = new CTimer(o => + { + Connect(); + ReconnectTimer = null; + }, AutoReconnectIntervalMs); Debug.Console(1, this, "Attempting connection in {0} seconds", (float)(AutoReconnectIntervalMs / 1000)); } @@ -251,6 +287,8 @@ namespace PepperDash.Core Debug.Console(0, this, "SSH client error: {0}", e.Exception); UStatus = 4; } + Client.Disconnect(); + Client = null; Debug.Console(1, this, "Disconnected by remote"); IsConnected = false; HandleConnectionFailure(); diff --git a/Pepperdash Core/Pepperdash Core/Comm/GenericTcpIpClient.cs b/Pepperdash Core/Pepperdash Core/Comm/GenericTcpIpClient.cs index 93dee26..2ec5be1 100644 --- a/Pepperdash Core/Pepperdash Core/Comm/GenericTcpIpClient.cs +++ b/Pepperdash Core/Pepperdash Core/Comm/GenericTcpIpClient.cs @@ -11,7 +11,7 @@ using Newtonsoft.Json.Linq; namespace PepperDash.Core { - public class GenericTcpIpClient : Device, IBasicCommunication + public class GenericTcpIpClient : Device, IBasicCommunication, IAutoReconnect { public event EventHandler BytesReceived; public event EventHandler TextReceived; @@ -21,6 +21,9 @@ namespace PepperDash.Core public string Status { get { return Client.ClientStatus.ToString(); } } public string ConnectionFailure { get { return Client.ClientStatus.ToString(); } } + public bool AutoReconnect { get; set; } + public int AutoReconnectIntervalMs { get; set; } + public bool Connected { get { return Client.ClientStatus == SocketStatus.SOCKET_STATUS_CONNECTED; } @@ -173,9 +176,21 @@ namespace PepperDash.Core /// public int BufferSize { get; set; } + /// + /// Defaults to true + /// + public bool AutoReconnect { get; set; } + + /// + /// Defaults to 5000ms + /// + public int AutoReconnectIntervalMs { get; set; } + public TcpIpConfig() { BufferSize = 32768; + AutoReconnect = true; + AutoReconnectIntervalMs = 5000; } } diff --git a/Pepperdash Core/Pepperdash Core/CommunicationExtras.cs b/Pepperdash Core/Pepperdash Core/CommunicationExtras.cs index a935d5e..fc50f0f 100644 --- a/Pepperdash Core/Pepperdash Core/CommunicationExtras.cs +++ b/Pepperdash Core/Pepperdash Core/CommunicationExtras.cs @@ -23,6 +23,12 @@ namespace PepperDash.Core void Connect(); } + public interface IAutoReconnect + { + bool AutoReconnect { get; set; } + int AutoReconnectIntervalMs { get; set; } + } + /// /// /// diff --git a/Pepperdash Core/Pepperdash Core/PepperDash_Core.csproj b/Pepperdash Core/Pepperdash Core/PepperDash_Core.csproj index 45c8b85..b55d637 100644 --- a/Pepperdash Core/Pepperdash Core/PepperDash_Core.csproj +++ b/Pepperdash Core/Pepperdash Core/PepperDash_Core.csproj @@ -82,7 +82,7 @@ C:\Users\hvolm\Desktop\working\pepperdash-simplsharp-core\Pepperdash Core\Pepperdash Core\bin\PepperDash_Core.clz 1.007.0017 - 8/3/2016 4:33:09 PM + 8/4/2016 12:58:52 PM False diff --git a/Pepperdash Core/Pepperdash Core/bin/PepperDash_Core.clz b/Pepperdash Core/Pepperdash Core/bin/PepperDash_Core.clz index 5fbbc27..bb723cc 100644 Binary files a/Pepperdash Core/Pepperdash Core/bin/PepperDash_Core.clz and b/Pepperdash Core/Pepperdash Core/bin/PepperDash_Core.clz differ diff --git a/Pepperdash Core/Pepperdash Core/bin/PepperDash_Core.config b/Pepperdash Core/Pepperdash Core/bin/PepperDash_Core.config index 4c3f1bb..593879c 100644 --- a/Pepperdash Core/Pepperdash Core/bin/PepperDash_Core.config +++ b/Pepperdash Core/Pepperdash Core/bin/PepperDash_Core.config @@ -10,7 +10,7 @@ - 8/3/2016 4:33:09 PM - 1.0.0.27993 + 8/4/2016 12:58:52 PM + 1.0.0.21565 \ No newline at end of file diff --git a/Pepperdash Core/Pepperdash Core/bin/manifest.info b/Pepperdash Core/Pepperdash Core/bin/manifest.info index 1fef01c..0949a69 100644 --- a/Pepperdash Core/Pepperdash Core/bin/manifest.info +++ b/Pepperdash Core/Pepperdash Core/bin/manifest.info @@ -1,4 +1,4 @@ -MainAssembly=PepperDash_Core.dll:ca423b7b3c2fe76c3d6a8b9cb9ff67cd +MainAssembly=PepperDash_Core.dll:1e2af81f50d343b460b7e2684b9db8fe MainAssemblyMinFirmwareVersion=1.007.0017 ü DependencySource=Newtonsoft.Json.Compact.dll:ea996aa2ec65aa1878e7c9d09e37a896 diff --git a/Pepperdash Core/Pepperdash Core/bin/manifest.ser b/Pepperdash Core/Pepperdash Core/bin/manifest.ser index 82edbc6..e52d1c5 100644 Binary files a/Pepperdash Core/Pepperdash Core/bin/manifest.ser and b/Pepperdash Core/Pepperdash Core/bin/manifest.ser differ