diff --git a/Pepperdash Core/Pepperdash Core/Comm/GenericSocketStatusChangeEventArgs.cs b/Pepperdash Core/Pepperdash Core/Comm/GenericSocketStatusChangeEventArgs.cs index 3a388ee..1f8dd09 100644 --- a/Pepperdash Core/Pepperdash Core/Comm/GenericSocketStatusChangeEventArgs.cs +++ b/Pepperdash Core/Pepperdash Core/Comm/GenericSocketStatusChangeEventArgs.cs @@ -9,4 +9,21 @@ using Crestron.SimplSharp.CrestronSockets; namespace PepperDash.Core { public delegate void GenericSocketStatusChangeEventDelegate(ISocketStatus client); + + + /// + /// + /// + public class GenericSocketStatusChageEventArgs : EventArgs + { + public ISocketStatus Client { get; private set; } + + public GenericSocketStatusChageEventArgs() { } + + public GenericSocketStatusChageEventArgs(ISocketStatus client) + { + Client = client; + } + } + } \ No newline at end of file diff --git a/Pepperdash Core/Pepperdash Core/Comm/GenericSshClient.cs b/Pepperdash Core/Pepperdash Core/Comm/GenericSshClient.cs index e788a7e..16ccff2 100644 --- a/Pepperdash Core/Pepperdash Core/Comm/GenericSshClient.cs +++ b/Pepperdash Core/Pepperdash Core/Comm/GenericSshClient.cs @@ -26,13 +26,12 @@ namespace PepperDash.Core /// /// Event when the connection status changes. /// - //[Obsolete("Use SocketStatusChange instead")] - //public event EventHandler ConnectionChange; + public event EventHandler ConnectionChange; /// /// /// - public event GenericSocketStatusChangeEventDelegate SocketStatusChange; + //public event GenericSocketStatusChangeEventDelegate SocketStatusChange; /// /// Address of server @@ -63,6 +62,14 @@ namespace PepperDash.Core get { return ClientStatus == SocketStatus.SOCKET_STATUS_CONNECTED; } } + /// + /// S+ helper for IsConnected + /// + public ushort UIsConnected + { + get { return (ushort)(IsConnected ? 1 : 0); } + } + /// /// /// @@ -93,6 +100,11 @@ namespace PepperDash.Core /// public bool AutoReconnect { get; set; } + /// + /// Will be set and unset by connect and disconnect only + /// + public bool ConnectEnabled { get; private set; } + /// /// S+ helper for AutoReconnect /// @@ -109,13 +121,15 @@ namespace PepperDash.Core public int AutoReconnectIntervalMs { get; set; } SshClient Client; + ShellStream TheStream; + CTimer ReconnectTimer; - string PreviousHostname; - int PreviousPort; - string PreviousUsername; - string PreviousPassword; + //string PreviousHostname; + //int PreviousPort; + //string PreviousUsername; + //string PreviousPassword; /// /// Typical constructor. @@ -171,7 +185,8 @@ namespace PepperDash.Core /// public void Connect() { - Debug.Console(1, this, "attempting connect, IsConnected={0}", Client != null ? Client.IsConnected : false); + ConnectEnabled = true; + Debug.Console(1, this, "attempting connect"); // Cancel reconnect if running. if (ReconnectTimer != null) @@ -197,55 +212,56 @@ namespace PepperDash.Core kauth.AuthenticationPrompt += new EventHandler(kauth_AuthenticationPrompt); PasswordAuthenticationMethod pauth = new PasswordAuthenticationMethod(Username, Password); - // always spin up new client in case parameters have changed - // **** MAY WANT TO CHANGE THIS BECAUSE OF SOCKET LEAKS **** - //if (Client != null) - //{ - // Client.Disconnect(); - // Client = null; - //} - // Make a new client if we need it or things have changed - if (Client == null || PropertiesHaveChanged()) - { + //if (Client == null || PropertiesHaveChanged()) + //{ if (Client != null) { Debug.Console(2, this, "Cleaning up disconnected client"); Client.ErrorOccurred -= Client_ErrorOccurred; - if(TheStream != null) - TheStream.DataReceived -= Stream_DataReceived; - TheStream = null; + KillStream(); + + //if (TheStream != null) + //{ + // TheStream.DataReceived -= Stream_DataReceived; + // TheStream.ErrorOccurred -= TheStream_ErrorOccurred; + //} + //TheStream = null; } Debug.Console(2, this, "Creating new SshClient"); ConnectionInfo connectionInfo = new ConnectionInfo(Hostname, Port, Username, pauth, kauth); Client = new SshClient(connectionInfo); Client.ErrorOccurred += Client_ErrorOccurred; - } - PreviousHostname = Hostname; - PreviousPassword = Password; - PreviousPort = Port; - PreviousUsername = Username; + //} + //PreviousHostname = Hostname; + //PreviousPassword = Password; + //PreviousPort = Port; + //PreviousUsername = Username; //You can do it! ClientStatus = SocketStatus.SOCKET_STATUS_WAITING; try { Client.Connect(); - if (Client.IsConnected) - { - Client.KeepAliveInterval = TimeSpan.FromSeconds(2); - Client.SendKeepAlive(); + + // Have to assume client is connected cause Client.IsConnected is busted in some cases + // All other conditions *should* error out... + //if (Client.IsConnected) + //{ + //Client.KeepAliveInterval = TimeSpan.FromSeconds(2); + //Client.SendKeepAlive(); TheStream = Client.CreateShellStream("PDTShell", 100, 80, 100, 200, 65534); TheStream.DataReceived += Stream_DataReceived; + //TheStream.ErrorOccurred += TheStream_ErrorOccurred; Debug.Console(1, this, "Connected"); ClientStatus = SocketStatus.SOCKET_STATUS_CONNECTED; - PreviousHostname = Hostname; - PreviousPassword = Password; - PreviousPort = Port; - PreviousUsername = Username; - } - return; + //PreviousHostname = Hostname; + //PreviousPassword = Password; + //PreviousPort = Port; + //PreviousUsername = Username; + //} + return; // Success will not pass here } catch (SshConnectionException e) { @@ -269,54 +285,44 @@ namespace PepperDash.Core } // Sucess will not make it this far - Client.Disconnect(); ClientStatus = SocketStatus.SOCKET_STATUS_CONNECT_FAILED; HandleConnectionFailure(); } + + /// /// Disconnect the clients and put away it's resources. /// public void Disconnect() { + ConnectEnabled = false; // Stop trying reconnects, if we are if (ReconnectTimer != null) { ReconnectTimer.Stop(); ReconnectTimer = null; } - if(TheStream != null) - TheStream.DataReceived -= Stream_DataReceived; + KillStream(); Client.Disconnect(); + Client = null; ClientStatus = SocketStatus.SOCKET_STATUS_BROKEN_LOCALLY; Debug.Console(1, this, "Disconnected"); } - /// - /// - /// - //void DiscoAndCleanup() - //{ - // if (Client != null) - // { - // Client.ErrorOccurred -= Client_ErrorOccurred; - // TheStream.DataReceived -= Stream_DataReceived; - // Debug.Console(2, this, "Cleaning up disconnected client"); - // Client.Disconnect(); - // Client.Dispose(); - // Client = null; - // } - //} - /// /// Anything to do with reestablishing connection on failures /// void HandleConnectionFailure() { - Debug.Console(2, this, "Checking autoreconnect: {0}, {1}ms", - AutoReconnect, AutoReconnectIntervalMs); - if (AutoReconnect) + if (Client != null) + Client.Disconnect(); + KillStream(); + + if (AutoReconnect && ConnectEnabled) { + Debug.Console(2, this, "Checking autoreconnect: {0}, {1}ms", + AutoReconnect, AutoReconnectIntervalMs); if (ReconnectTimer == null)// || !ReconnectTimerRunning) { ReconnectTimer = new CTimer(o => @@ -335,12 +341,24 @@ namespace PepperDash.Core } } - bool PropertiesHaveChanged() + void KillStream() { - return Hostname != PreviousHostname || Port != PreviousPort - || Username != PreviousUsername || Password != PreviousPassword; + if (TheStream != null) + { + TheStream.DataReceived -= Stream_DataReceived; + //TheStream.ErrorOccurred -= TheStream_ErrorOccurred; + TheStream.Close(); + TheStream.Dispose(); + TheStream = null; + } } + //bool PropertiesHaveChanged() + //{ + // return Hostname != PreviousHostname || Port != PreviousPort + // || Username != PreviousUsername || Password != PreviousPassword; + //} + /// /// Handles the keyboard interactive authentication, should it be required. /// @@ -371,23 +389,29 @@ namespace PepperDash.Core } } + ///// + ///// Handler for errors on the stream... + ///// + ///// + ///// + //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(); + //} + /// /// Error event handler for client events - disconnect, etc. Will forward those events via ConnectionChange /// event /// void Client_ErrorOccurred(object sender, Crestron.SimplSharp.Ssh.Common.ExceptionEventArgs e) { - Debug.Console(1, this, "SSH client error: {0}", e.Exception); - if (!(e.Exception is SshConnectionException)) - { + if (e.Exception is SshConnectionException || e.Exception is System.Net.Sockets.SocketException) Debug.Console(1, this, "Disconnected by remote"); - } - if (Client != null) - { - Client.Disconnect(); - //Client.Dispose(); - //Client = null; - } + else + Debug.Console(1, this, "Unhandled SSH client error: {0}", e.Exception); + ClientStatus = SocketStatus.SOCKET_STATUS_BROKEN_REMOTELY; HandleConnectionFailure(); } @@ -397,12 +421,8 @@ namespace PepperDash.Core /// void OnConnectionChange() { - //if(ConnectionChange != null) - // ConnectionChange(this, new SshConnectionChangeEventArgs(IsConnected, this)); - - var handler = SocketStatusChange; - if (handler != null) - SocketStatusChange(this); + if (ConnectionChange != null) + ConnectionChange(this, new GenericSocketStatusChageEventArgs(this)); } #region IBasicCommunication Members diff --git a/Pepperdash Core/Pepperdash Core/Comm/GenericTcpIpClient.cs b/Pepperdash Core/Pepperdash Core/Comm/GenericTcpIpClient.cs index 85fc901..8b30fe6 100644 --- a/Pepperdash Core/Pepperdash Core/Comm/GenericTcpIpClient.cs +++ b/Pepperdash Core/Pepperdash Core/Comm/GenericTcpIpClient.cs @@ -26,7 +26,8 @@ namespace PepperDash.Core /// /// /// - public event GenericSocketStatusChangeEventDelegate SocketStatusChange; + //public event GenericSocketStatusChangeEventDelegate SocketStatusChange; + public event EventHandler ConnectionChange; /// /// @@ -207,10 +208,14 @@ namespace PepperDash.Core break; } - // Relay the event - var handler = SocketStatusChange; + var handler = ConnectionChange; if (handler != null) - SocketStatusChange(this); + ConnectionChange(this, new GenericSocketStatusChageEventArgs(this)); + + // Relay the event + //var handler = SocketStatusChange; + //if (handler != null) + // SocketStatusChange(this); } } diff --git a/Pepperdash Core/Pepperdash Core/CommunicationExtras.cs b/Pepperdash Core/Pepperdash Core/CommunicationExtras.cs index 73917b1..e369fa7 100644 --- a/Pepperdash Core/Pepperdash Core/CommunicationExtras.cs +++ b/Pepperdash Core/Pepperdash Core/CommunicationExtras.cs @@ -31,7 +31,7 @@ namespace PepperDash.Core /// public interface ISocketStatus : IBasicCommunication { - event GenericSocketStatusChangeEventDelegate SocketStatusChange; + event EventHandler ConnectionChange; SocketStatus ClientStatus { get; } } diff --git a/Pepperdash Core/Pepperdash Core/Debug/Debug.cs b/Pepperdash Core/Pepperdash Core/Debug/Debug.cs index fe59717..2c52a2b 100644 --- a/Pepperdash Core/Pepperdash Core/Debug/Debug.cs +++ b/Pepperdash Core/Pepperdash Core/Debug/Debug.cs @@ -32,11 +32,7 @@ namespace PepperDash.Core static CTimer SaveTimer; - /// - /// This should called from the ControlSystem Initiailize method. Will attempt to call - /// CrestronDataStoreStatic.InitCrestronDataStore which may have been called elsewhere. - /// - public static void Initialize() + static Debug() { CrestronDataStoreStatic.InitCrestronDataStore(); if (CrestronEnvironment.RuntimeEnvironment == eRuntimeEnvironment.SimplSharpPro) @@ -53,6 +49,27 @@ namespace PepperDash.Core Level = Contexts.GetOrCreateItem("DEFAULT").Level; } + /// + /// This should called from the ControlSystem Initiailize method. Will attempt to call + /// CrestronDataStoreStatic.InitCrestronDataStore which may have been called elsewhere. + /// + public static void Initialize() + { + //CrestronDataStoreStatic.InitCrestronDataStore(); + //if (CrestronEnvironment.RuntimeEnvironment == eRuntimeEnvironment.SimplSharpPro) + //{ + // // Add command to console + // CrestronConsole.AddNewConsoleCommand(SetDebugFromConsole, "appdebug", + // "appdebug:P [0-2]: Sets the application's console debug message level", + // ConsoleAccessLevelEnum.AccessOperator); + //} + + //CrestronEnvironment.ProgramStatusEventHandler += CrestronEnvironment_ProgramStatusEventHandler; + + //LoadMemory(); + //Level = Contexts.GetOrCreateItem("DEFAULT").Level; + } + /// /// Used to save memory when shutting down /// diff --git a/Pepperdash Core/Pepperdash Core/PepperDash_Core.projectinfo b/Pepperdash Core/Pepperdash Core/PepperDash_Core.projectinfo index aa26281..eb0cc56 100644 Binary files a/Pepperdash Core/Pepperdash Core/PepperDash_Core.projectinfo and b/Pepperdash Core/Pepperdash Core/PepperDash_Core.projectinfo differ diff --git a/Pepperdash Core/Pepperdash Core/Properties/ControlSystem.cfg b/Pepperdash Core/Pepperdash Core/Properties/ControlSystem.cfg index 5dff7ae..276e200 100644 --- a/Pepperdash Core/Pepperdash Core/Properties/ControlSystem.cfg +++ b/Pepperdash Core/Pepperdash Core/Properties/ControlSystem.cfg @@ -2,6 +2,6 @@ MC3 SSH
ssh 10.0.0.15
- - + Program01 + Internal Flash
\ No newline at end of file diff --git a/Pepperdash Core/Pepperdash Core/bin/PepperDash_Core.clz b/Pepperdash Core/Pepperdash Core/bin/PepperDash_Core.clz index 89cf368..2625922 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 33a2e5b..c5ec08c 100644 --- a/Pepperdash Core/Pepperdash Core/bin/PepperDash_Core.config +++ b/Pepperdash Core/Pepperdash Core/bin/PepperDash_Core.config @@ -10,8 +10,8 @@ - 11/28/2016 1:59:52 PM - 1.0.0.25195 + 12/6/2016 4:09:28 PM + 1.0.0.29083 Crestron.SIMPLSharp, Version=2.0.48.0, Culture=neutral, PublicKeyToken=812d080f93e2de10 diff --git a/Pepperdash Core/Pepperdash Core/bin/PepperDash_Core.dll b/Pepperdash Core/Pepperdash Core/bin/PepperDash_Core.dll index f038257..d4bb232 100644 Binary files a/Pepperdash Core/Pepperdash Core/bin/PepperDash_Core.dll and b/Pepperdash Core/Pepperdash Core/bin/PepperDash_Core.dll differ diff --git a/Pepperdash Core/Pepperdash Core/bin/manifest.info b/Pepperdash Core/Pepperdash Core/bin/manifest.info index 5d87102..96f81fa 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:91882e81937f6bb6c3592368dedeea09 +MainAssembly=PepperDash_Core.dll:987a92dfd5c1b46ff22b2570acef6436 MainAssemblyMinFirmwareVersion=1.007.0017 MainAssemblyResource=SimplSharpData.dat:315526abf906cded47fb0c7510266a7e ü diff --git a/Pepperdash Core/Pepperdash Core/bin/manifest.ser b/Pepperdash Core/Pepperdash Core/bin/manifest.ser index 9b266a9..091c5d1 100644 Binary files a/Pepperdash Core/Pepperdash Core/bin/manifest.ser and b/Pepperdash Core/Pepperdash Core/bin/manifest.ser differ