diff --git a/Pepperdash Core/Pepperdash Core/Comm/._GenericSshClient.cs b/Pepperdash Core/Pepperdash Core/Comm/._GenericSshClient.cs
new file mode 100644
index 0000000..583c583
Binary files /dev/null and b/Pepperdash Core/Pepperdash Core/Comm/._GenericSshClient.cs differ
diff --git a/Pepperdash Core/Pepperdash Core/Comm/._GenericTcpIpClient.cs b/Pepperdash Core/Pepperdash Core/Comm/._GenericTcpIpClient.cs
new file mode 100644
index 0000000..b65487e
Binary files /dev/null and b/Pepperdash Core/Pepperdash Core/Comm/._GenericTcpIpClient.cs differ
diff --git a/Pepperdash Core/Pepperdash Core/Comm/GenericSshClient.cs b/Pepperdash Core/Pepperdash Core/Comm/GenericSshClient.cs
index b61a39e..4ac42fa 100644
--- a/Pepperdash Core/Pepperdash Core/Comm/GenericSshClient.cs
+++ b/Pepperdash Core/Pepperdash Core/Comm/GenericSshClient.cs
@@ -65,11 +65,9 @@ namespace PepperDash.Core
public bool IsConnected
{
// returns false if no client or not connected
- get { return ClientStatus == SocketStatus.SOCKET_STATUS_CONNECTED; }
+ get { return Client != null && ClientStatus == SocketStatus.SOCKET_STATUS_CONNECTED; }
}
- private bool IsConnecting = false;
-
///
/// S+ helper for IsConnected
///
@@ -134,10 +132,10 @@ namespace PepperDash.Core
CTimer ReconnectTimer;
- //string PreviousHostname;
- //int PreviousPort;
- //string PreviousUsername;
- //string PreviousPassword;
+ //Lock object to prevent simulatneous connect/disconnect operations
+ private CCriticalSection connectLock = new CCriticalSection();
+
+ private bool DisconnectLogged = false;
///
/// Typical constructor.
@@ -153,6 +151,14 @@ namespace PepperDash.Core
Username = username;
Password = password;
AutoReconnectIntervalMs = 5000;
+
+ ReconnectTimer = new CTimer(o =>
+ {
+ if (ConnectEnabled)
+ {
+ Connect();
+ }
+ }, Timeout.Infinite);
}
///
@@ -161,9 +167,16 @@ namespace PepperDash.Core
public GenericSshClient()
: base(SPlusKey)
{
- StreamDebugging = new CommunicationStreamDebugging(SPlusKey);
CrestronEnvironment.ProgramStatusEventHandler += new ProgramStatusEventHandler(CrestronEnvironment_ProgramStatusEventHandler);
AutoReconnectIntervalMs = 5000;
+
+ ReconnectTimer = new CTimer(o =>
+ {
+ if (ConnectEnabled)
+ {
+ Connect();
+ }
+ }, Timeout.Infinite);
}
///
@@ -194,115 +207,122 @@ namespace PepperDash.Core
///
public void Connect()
{
- if (IsConnecting)
- {
- Debug.Console(0, this, Debug.ErrorLogLevel.Warning, "Connection attempt in progress. Exiting Connect()");
- return;
- }
-
- IsConnecting = true;
- ConnectEnabled = true;
- Debug.Console(1, this, "attempting connect");
-
- // Cancel reconnect if running.
- if (ReconnectTimer != null)
- {
- ReconnectTimer.Stop();
- ReconnectTimer = null;
- }
-
- // Don't try to connect if already
- if (IsConnected)
- return;
-
// Don't go unless everything is here
if (string.IsNullOrEmpty(Hostname) || Port < 1 || Port > 65535
|| Username == null || Password == null)
{
- Debug.Console(1, this, Debug.ErrorLogLevel.Error, "Connect failed. Check hostname, port, username and password are set or not null");
+ Debug.Console(0, this, Debug.ErrorLogLevel.Error, "Connect failed. Check hostname, port, username and password are set or not null");
return;
}
- // Cleanup the old client if it already exists
- if (Client != null)
- {
- Debug.Console(1, this, "Cleaning up disconnected client");
- Client.ErrorOccurred -= Client_ErrorOccurred;
- KillClient(SocketStatus.SOCKET_STATUS_BROKEN_LOCALLY);
- }
+ ConnectEnabled = true;
- // 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);
-
- Debug.Console(1, this, "Creating new SshClient");
- ConnectionInfo connectionInfo = new ConnectionInfo(Hostname, Port, Username, pauth, kauth);
- Client = new SshClient(connectionInfo);
-
- Client.ErrorOccurred -= Client_ErrorOccurred;
- Client.ErrorOccurred += Client_ErrorOccurred;
-
- //Attempt to connect
- ClientStatus = SocketStatus.SOCKET_STATUS_WAITING;
try
{
- Client.Connect();
- TheStream = Client.CreateShellStream("PDTShell", 100, 80, 100, 200, 65534);
- TheStream.DataReceived += Stream_DataReceived;
- //TheStream.ErrorOccurred += TheStream_ErrorOccurred;
- Debug.Console(1, this, Debug.ErrorLogLevel.Notice, "Connected");
- ClientStatus = SocketStatus.SOCKET_STATUS_CONNECTED;
- IsConnecting = false;
- return; // Success will not pass here
- }
- catch (SshConnectionException e)
- {
- var ie = e.InnerException; // The details are inside!!
- if (ie is SocketException)
- Debug.Console(1, this, Debug.ErrorLogLevel.Error, "'{0}' CONNECTION failure: Cannot reach host, ({1})", Key, ie.Message);
- else if (ie is System.Net.Sockets.SocketException)
- Debug.Console(1, this, Debug.ErrorLogLevel.Error, "'{0}' Connection failure: Cannot reach host '{1}' on port {2}, ({3})",
- Key, Hostname, Port, ie.GetType());
- else if (ie is SshAuthenticationException)
+ connectLock.Enter();
+ if (IsConnected)
{
- Debug.Console(1, this, Debug.ErrorLogLevel.Error, "Authentication failure for username '{0}', ({1})",
- Username, ie.Message);
+ Debug.Console(1, this, "Connection already connected. Exiting Connect()");
}
else
- Debug.Console(1, this, Debug.ErrorLogLevel.Error, "Error on connect:\r({0})", e);
+ {
+ Debug.Console(1, this, "Attempting connect");
- ClientStatus = SocketStatus.SOCKET_STATUS_CONNECT_FAILED;
- HandleConnectionFailure();
+ // Cancel reconnect if running.
+ ReconnectTimer.Stop();
+
+ // Cleanup the old client if it already exists
+ if (Client != null)
+ {
+ Debug.Console(1, this, "Cleaning up disconnected client");
+ KillClient(SocketStatus.SOCKET_STATUS_BROKEN_LOCALLY);
+ }
+
+ // 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);
+
+ Debug.Console(1, this, "Creating new SshClient");
+ ConnectionInfo connectionInfo = new ConnectionInfo(Hostname, Port, Username, pauth, kauth);
+ Client = new SshClient(connectionInfo);
+
+ Client.ErrorOccurred -= Client_ErrorOccurred;
+ Client.ErrorOccurred += Client_ErrorOccurred;
+
+ //Attempt to connect
+ ClientStatus = SocketStatus.SOCKET_STATUS_WAITING;
+ try
+ {
+ Client.Connect();
+ TheStream = Client.CreateShellStream("PDTShell", 100, 80, 100, 200, 65534);
+ TheStream.DataReceived += Stream_DataReceived;
+ Debug.Console(1, this, Debug.ErrorLogLevel.Notice, "Connected");
+ ClientStatus = SocketStatus.SOCKET_STATUS_CONNECTED;
+ DisconnectLogged = false;
+ }
+ catch (SshConnectionException e)
+ {
+ var ie = e.InnerException; // The details are inside!!
+ var errorLogLevel = DisconnectLogged == true ? Debug.ErrorLogLevel.None : Debug.ErrorLogLevel.Error;
+
+ if (ie is SocketException)
+ Debug.Console(1, this, errorLogLevel, "'{0}' CONNECTION failure: Cannot reach host, ({1})", Key, ie.Message);
+ else if (ie is System.Net.Sockets.SocketException)
+ Debug.Console(1, this, errorLogLevel, "'{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, errorLogLevel, "Authentication failure for username '{0}', ({1})",
+ Username, ie.Message);
+ }
+ else
+ Debug.Console(1, this, errorLogLevel, "Error on connect:\r({0})", ie.Message);
+
+ DisconnectLogged = true;
+ KillClient(SocketStatus.SOCKET_STATUS_CONNECT_FAILED);
+ if (AutoReconnect)
+ {
+ Debug.Console(1, this, "Checking autoreconnect: {0}, {1}ms", AutoReconnect, AutoReconnectIntervalMs);
+ ReconnectTimer.Reset(AutoReconnectIntervalMs);
+ }
+ }
+ catch (Exception e)
+ {
+ var errorLogLevel = DisconnectLogged == true ? Debug.ErrorLogLevel.None : Debug.ErrorLogLevel.Error;
+ Debug.Console(1, this, errorLogLevel, "Unhandled exception on connect:\r({0})", e.Message);
+ DisconnectLogged = true;
+ KillClient(SocketStatus.SOCKET_STATUS_CONNECT_FAILED);
+ if (AutoReconnect)
+ {
+ Debug.Console(1, this, "Checking autoreconnect: {0}, {1}ms", AutoReconnect, AutoReconnectIntervalMs);
+ ReconnectTimer.Reset(AutoReconnectIntervalMs);
+ }
+ }
+ }
}
- catch (Exception e)
+ finally
{
- Debug.Console(1, this, Debug.ErrorLogLevel.Error, "Unhandled exception on connect:\r({0})", e);
- ClientStatus = SocketStatus.SOCKET_STATUS_CONNECT_FAILED;
- HandleConnectionFailure();
+ connectLock.Leave();
}
-
- ClientStatus = SocketStatus.SOCKET_STATUS_CONNECT_FAILED;
- HandleConnectionFailure();
}
-
-
///
/// Disconnect the clients and put away it's resources.
///
public void Disconnect()
{
- Debug.Console(2, "Disconnect Called");
- ConnectEnabled = false;
- // Stop trying reconnects, if we are
- if (ReconnectTimer != null)
- {
- ReconnectTimer.Stop();
- ReconnectTimer = null;
- }
-
- KillClient(SocketStatus.SOCKET_STATUS_BROKEN_LOCALLY);
+ try
+ {
+ connectLock.Enter();
+ // Stop trying reconnects, if we are
+ ReconnectTimer.Stop();
+ KillClient(SocketStatus.SOCKET_STATUS_BROKEN_LOCALLY);
+ }
+ finally
+ {
+ connectLock.Leave();
+ }
}
///
@@ -314,44 +334,21 @@ namespace PepperDash.Core
IsConnecting = false;
if (Client != null)
{
- Client.ErrorOccurred -= Client_ErrorOccurred;
- Client.Disconnect();
- Client.Dispose();
-
- Client = null;
- ClientStatus = status;
- Debug.Console(1, this, "Disconnected");
+ try
+ {
+ Client.Disconnect();
+ Client.Dispose();
+ Client = null;
+ ClientStatus = status;
+ Debug.Console(1, this, "Disconnected client");
+ }
+ catch (Exception ex)
+ {
+ Debug.Console(1, this, "Exception killing client: {0}", ex.Message);
+ }
}
}
- ///
- /// Anything to do with reestablishing connection on failures
- ///
- void HandleConnectionFailure()
- {
- KillClient(SocketStatus.SOCKET_STATUS_CONNECT_FAILED);
-
- Debug.Console(1, this, "Client nulled due to connection failure. AutoReconnect: {0}, ConnectEnabled: {1}", AutoReconnect, ConnectEnabled);
- if (AutoReconnect && ConnectEnabled)
- {
- Debug.Console(1, this, "Checking autoreconnect: {0}, {1}ms", AutoReconnect, AutoReconnectIntervalMs);
- if (ReconnectTimer == null)
- {
- ReconnectTimer = new CTimer(o =>
- {
- Connect();
- }, AutoReconnectIntervalMs);
- Debug.Console(1, this, Debug.ErrorLogLevel.Notice, "Attempting connection in {0} seconds",
- (float) (AutoReconnectIntervalMs/1000));
- }
- else
- {
- Debug.Console(1, this, "{0} second reconnect cycle running",
- (float) (AutoReconnectIntervalMs/1000));
- }
- }
- }
-
///
/// Kills the stream
///
@@ -363,6 +360,7 @@ namespace PepperDash.Core
TheStream.Close();
TheStream.Dispose();
TheStream = null;
+ Debug.Console(1, this, "Disconnected stream");
}
}
@@ -413,13 +411,28 @@ namespace PepperDash.Core
///
void Client_ErrorOccurred(object sender, Crestron.SimplSharp.Ssh.Common.ExceptionEventArgs e)
{
- if (e.Exception is SshConnectionException || e.Exception is System.Net.Sockets.SocketException)
- Debug.Console(1, this, Debug.ErrorLogLevel.Error, "Disconnected by remote");
- else
- Debug.Console(1, this, Debug.ErrorLogLevel.Error, "Unhandled SSH client error: {0}", e.Exception);
+ CrestronInvoke.BeginInvoke(o =>
+ {
+ if (e.Exception is SshConnectionException || e.Exception is System.Net.Sockets.SocketException)
+ Debug.Console(1, this, Debug.ErrorLogLevel.Error, "Disconnected by remote");
+ else
+ Debug.Console(1, this, Debug.ErrorLogLevel.Error, "Unhandled SSH client error: {0}", e.Exception);
- ClientStatus = SocketStatus.SOCKET_STATUS_BROKEN_REMOTELY;
- HandleConnectionFailure();
+ try
+ {
+ connectLock.Enter();
+ KillClient(SocketStatus.SOCKET_STATUS_BROKEN_REMOTELY);
+ }
+ finally
+ {
+ connectLock.Leave();
+ }
+ if (AutoReconnect && ConnectEnabled)
+ {
+ Debug.Console(1, this, "Checking autoreconnect: {0}, {1}ms", AutoReconnect, AutoReconnectIntervalMs);
+ ReconnectTimer.Reset(AutoReconnectIntervalMs);
+ }
+ });
}
///
@@ -461,8 +474,6 @@ namespace PepperDash.Core
Debug.Console(0, "Stack Trace: {0}", ex.StackTrace);
Debug.Console(1, this, Debug.ErrorLogLevel.Error, "Stream write failed. Disconnected, closing");
- ClientStatus = SocketStatus.SOCKET_STATUS_BROKEN_REMOTELY;
- HandleConnectionFailure();
}
}
@@ -490,8 +501,6 @@ namespace PepperDash.Core
catch
{
Debug.Console(1, this, Debug.ErrorLogLevel.Error, "Stream write failed. Disconnected, closing");
- ClientStatus = SocketStatus.SOCKET_STATUS_BROKEN_REMOTELY;
- HandleConnectionFailure();
}
}
diff --git a/Pepperdash Core/Pepperdash Core/Comm/GenericTcpIpClient.cs b/Pepperdash Core/Pepperdash Core/Comm/GenericTcpIpClient.cs
index 16013a3..8cfaad2 100644
--- a/Pepperdash Core/Pepperdash Core/Comm/GenericTcpIpClient.cs
+++ b/Pepperdash Core/Pepperdash Core/Comm/GenericTcpIpClient.cs
@@ -5,9 +5,7 @@ using System.Text;
using System.Text.RegularExpressions;
using Crestron.SimplSharp;
using Crestron.SimplSharp.CrestronSockets;
-
using Newtonsoft.Json;
-using Newtonsoft.Json.Linq;
namespace PepperDash.Core
{
@@ -39,23 +37,24 @@ namespace PepperDash.Core
public event EventHandler ConnectionChange;
- private string _Hostname { get; set;}
+ private string _hostname;
+
///
/// Address of server
///
- public string Hostname {
+ public string Hostname
+ {
get
{
- return _Hostname;
+ return _hostname;
}
set
{
- _Hostname = value;
- if (Client != null)
+ _hostname = value;
+ if (_client != null)
{
-
- Client.AddressClientConnectedTo = _Hostname;
+ _client.AddressClientConnectedTo = _hostname;
}
}
}
@@ -83,14 +82,14 @@ namespace PepperDash.Core
///
/// The actual client class
///
- public TCPClient Client { get; private set; }
+ private TCPClient _client;
///
- /// True if connected to the server
+ /// Bool showing if socket is connected
///
public bool IsConnected
{
- get { return Client != null && Client.ClientStatus == SocketStatus.SOCKET_STATUS_CONNECTED; }
+ get { return _client != null && _client.ClientStatus == SocketStatus.SOCKET_STATUS_CONNECTED; }
}
///
@@ -102,21 +101,19 @@ namespace PepperDash.Core
}
///
- /// Status of the socket
+ /// _client socket status Read only
///
public SocketStatus ClientStatus
{
get
{
- if (Client == null)
- return SocketStatus.SOCKET_STATUS_NO_CONNECT;
- return Client.ClientStatus;
+ return _client == null ? SocketStatus.SOCKET_STATUS_NO_CONNECT : _client.ClientStatus;
}
}
///
/// Contains the familiar Simpl analog status values. This drives the ConnectionChange event
- /// and IsConnected with be true when this == 2.
+ /// and IsConnected would be true when this == 2.
///
public ushort UStatus
{
@@ -124,7 +121,7 @@ namespace PepperDash.Core
}
///
- /// Status of the socket
+ /// Status text shows the message associated with socket status
///
public string ClientStatusText { get { return ClientStatus.ToString(); } }
@@ -140,7 +137,7 @@ namespace PepperDash.Core
public string ConnectionFailure { get { return ClientStatus.ToString(); } }
///
- /// If true, enables AutoConnect
+ /// bool to track if auto reconnect should be set on the socket
///
public bool AutoReconnect { get; set; }
@@ -152,13 +149,14 @@ namespace PepperDash.Core
get { return (ushort)(AutoReconnect ? 1 : 0); }
set { AutoReconnect = value == 1; }
}
+
///
/// Milliseconds to wait before attempting to reconnect. Defaults to 5000
///
public int AutoReconnectIntervalMs { get; set; }
///
- /// Set only when the disconnect method is called.
+ /// Set only when the disconnect method is called
///
bool DisconnectCalledByUser;
@@ -167,10 +165,14 @@ namespace PepperDash.Core
///
public bool Connected
{
- get { return Client.ClientStatus == SocketStatus.SOCKET_STATUS_CONNECTED; }
+ get { return _client.ClientStatus == SocketStatus.SOCKET_STATUS_CONNECTED; }
}
- CTimer RetryTimer;
+ //Lock object to prevent simulatneous connect/disconnect operations
+ private CCriticalSection connectLock = new CCriticalSection();
+
+ // private Timer for auto reconnect
+ private CTimer RetryTimer;
///
/// Constructor
@@ -183,13 +185,17 @@ namespace PepperDash.Core
: base(key)
{
StreamDebugging = new CommunicationStreamDebugging(key);
+ CrestronEnvironment.ProgramStatusEventHandler += new ProgramStatusEventHandler(CrestronEnvironment_ProgramStatusEventHandler);
+ AutoReconnectIntervalMs = 5000;
Hostname = address;
Port = port;
BufferSize = bufferSize;
- AutoReconnectIntervalMs = 5000;
- CrestronEnvironment.ProgramStatusEventHandler += new ProgramStatusEventHandler(CrestronEnvironment_ProgramStatusEventHandler);
- }
+ RetryTimer = new CTimer(o =>
+ {
+ Reconnect();
+ }, Timeout.Infinite);
+ }
///
/// Constructor
@@ -202,6 +208,11 @@ namespace PepperDash.Core
CrestronEnvironment.ProgramStatusEventHandler += new ProgramStatusEventHandler(CrestronEnvironment_ProgramStatusEventHandler);
AutoReconnectIntervalMs = 5000;
BufferSize = 2000;
+
+ RetryTimer = new CTimer(o =>
+ {
+ Reconnect();
+ }, Timeout.Infinite);
}
///
@@ -210,10 +221,14 @@ namespace PepperDash.Core
public GenericTcpIpClient()
: base(SplusKey)
{
- StreamDebugging = new CommunicationStreamDebugging(SplusKey);
CrestronEnvironment.ProgramStatusEventHandler += new ProgramStatusEventHandler(CrestronEnvironment_ProgramStatusEventHandler);
AutoReconnectIntervalMs = 5000;
BufferSize = 2000;
+
+ RetryTimer = new CTimer(o =>
+ {
+ Reconnect();
+ }, Timeout.Infinite);
}
///
@@ -232,7 +247,7 @@ namespace PepperDash.Core
if (programEventType == eProgramStatusEventType.Stopping)
{
Debug.Console(1, this, "Program stopping. Closing connection");
- Disconnect();
+ Deactivate();
}
}
@@ -242,9 +257,11 @@ namespace PepperDash.Core
///
public override bool Deactivate()
{
- if (Client != null)
+ RetryTimer.Stop();
+ RetryTimer.Dispose();
+ if (_client != null)
{
- Client.SocketStatusChange -= this.Client_SocketStatusChange;
+ _client.SocketStatusChange -= this.Client_SocketStatusChange;
DisconnectClient();
}
return true;
@@ -255,9 +272,6 @@ namespace PepperDash.Core
///
public void Connect()
{
- if (IsConnected)
- DisconnectClient();
-
if (string.IsNullOrEmpty(Hostname))
{
Debug.Console(1, Debug.ErrorLogLevel.Warning, "GenericTcpIpClient '{0}': No address set", Key);
@@ -271,36 +285,72 @@ namespace PepperDash.Core
}
}
- if (Client == null)
+ try
{
- Client = new TCPClient(Hostname, Port, BufferSize);
- Client.SocketStatusChange -= Client_SocketStatusChange;
- Client.SocketStatusChange += Client_SocketStatusChange;
+ connectLock.Enter();
+ if (IsConnected)
+ {
+ Debug.Console(1, this, "Connection already connected. Exiting Connect()");
+ }
+ else
+ {
+ //Stop retry timer if running
+ RetryTimer.Stop();
+ _client = new TCPClient(Hostname, Port, BufferSize);
+ _client.SocketStatusChange -= Client_SocketStatusChange;
+ _client.SocketStatusChange += Client_SocketStatusChange;
+ DisconnectCalledByUser = false;
+ _client.ConnectToServerAsync(ConnectToServerCallback);
+ }
+ }
+ finally
+ {
+ connectLock.Leave();
}
- DisconnectCalledByUser = false;
-
- Client.ConnectToServerAsync(ConnectToServerCallback); // (null);
}
+ private void Reconnect()
+ {
+ if (_client == null)
+ {
+ return;
+ }
+ try
+ {
+ connectLock.Enter();
+ if (IsConnected || DisconnectCalledByUser == true)
+ {
+ Debug.Console(1, this, "Reconnect no longer needed. Exiting Reconnect()");
+ }
+ else
+ {
+ Debug.Console(1, this, "Attempting reconnect now");
+ _client.ConnectToServerAsync(ConnectToServerCallback);
+ }
+ }
+ finally
+ {
+ connectLock.Leave();
+ }
+ }
+
///
/// Attempts to disconnect the client
///
public void Disconnect()
{
- DisconnectCalledByUser = true;
-
- // Stop trying reconnects, if we are
- if (RetryTimer != null)
+ try
{
+ connectLock.Enter();
+ DisconnectCalledByUser = true;
+
+ // Stop trying reconnects, if we are
RetryTimer.Stop();
- RetryTimer = null;
- }
-
- if (Client != null)
- {
DisconnectClient();
- Client = null;
- Debug.Console(1, this, "Disconnected");
+ }
+ finally
+ {
+ connectLock.Leave();
}
}
@@ -309,11 +359,11 @@ namespace PepperDash.Core
///
public void DisconnectClient()
{
- if (Client != null)
+ if (_client != null)
{
Debug.Console(1, this, "Disconnecting client");
- if(IsConnected)
- Client.DisconnectFromServer();
+ if (IsConnected)
+ _client.DisconnectFromServer();
}
}
@@ -323,9 +373,15 @@ namespace PepperDash.Core
///
void ConnectToServerCallback(TCPClient c)
{
- Debug.Console(1, this, "Server connection result: {0}", c.ClientStatus);
- if (c.ClientStatus != SocketStatus.SOCKET_STATUS_CONNECTED && AutoReconnect)
- WaitAndTryReconnect();
+ if (c.ClientStatus != SocketStatus.SOCKET_STATUS_CONNECTED)
+ {
+ Debug.Console(0, this, "Server connection result: {0}", c.ClientStatus);
+ WaitAndTryReconnect();
+ }
+ else
+ {
+ Debug.Console(1, this, "Server connection result: {0}", c.ClientStatus);
+ }
}
///
@@ -333,24 +389,23 @@ namespace PepperDash.Core
///
void WaitAndTryReconnect()
{
- DisconnectClient();
-
- if (Client != null)
+ CrestronInvoke.BeginInvoke(o =>
{
- Debug.Console(1, this, "Attempting reconnect, status={0}", Client.ClientStatus);
-
- if (!DisconnectCalledByUser)
- RetryTimer = new CTimer(o =>
+ try
+ {
+ connectLock.Enter();
+ if (!IsConnected && AutoReconnect && !DisconnectCalledByUser && _client != null)
{
- if (Client == null)
- {
- return;
- }
-
- Client.ConnectToServerAsync(ConnectToServerCallback);
- }, AutoReconnectIntervalMs);
- }
-
+ DisconnectClient();
+ Debug.Console(1, this, "Attempting reconnect, status={0}", _client.ClientStatus);
+ RetryTimer.Reset(AutoReconnectIntervalMs);
+ }
+ }
+ finally
+ {
+ connectLock.Leave();
+ }
+ });
}
///
@@ -380,15 +435,13 @@ namespace PepperDash.Core
var str = Encoding.GetEncoding(28591).GetString(bytes, 0, bytes.Length);
if (StreamDebugging.RxStreamDebuggingIsEnabled)
+ {
Debug.Console(0, this, "Received {1} characters of text: '{0}'", ComTextHelper.GetDebugText(str), str.Length);
+ }
textHandler(this, new GenericCommMethodReceiveTextArgs(str));
-
- }
-
-
+ }
}
-
client.ReceiveDataAsync(Receive);
}
}
@@ -402,10 +455,8 @@ namespace PepperDash.Core
// Check debug level before processing byte array
if (StreamDebugging.TxStreamDebuggingIsEnabled)
Debug.Console(0, this, "Sending {0} characters of text: '{1}'", text.Length, ComTextHelper.GetDebugText(text));
- if(Client != null)
- Client.SendData(bytes, bytes.Length);
-
-
+ if (_client != null)
+ _client.SendData(bytes, bytes.Length);
}
///
@@ -429,8 +480,8 @@ namespace PepperDash.Core
{
if (StreamDebugging.TxStreamDebuggingIsEnabled)
Debug.Console(0, this, "Sending {0} bytes: '{1}'", bytes.Length, ComTextHelper.GetEscapedText(bytes));
- if(Client != null)
- Client.SendData(bytes, bytes.Length);
+ if (_client != null)
+ _client.SendData(bytes, bytes.Length);
}
///
@@ -440,27 +491,20 @@ namespace PepperDash.Core
///
void Client_SocketStatusChange(TCPClient client, SocketStatus clientSocketStatus)
{
- Debug.Console(1, this, "Socket status change {0} ({1})", clientSocketStatus, ClientStatusText);
- if (client.ClientStatus != SocketStatus.SOCKET_STATUS_CONNECTED && !DisconnectCalledByUser && AutoReconnect)
- WaitAndTryReconnect();
-
- // Probably doesn't need to be a switch since all other cases were eliminated
- switch (clientSocketStatus)
- {
- case SocketStatus.SOCKET_STATUS_CONNECTED:
- Client.ReceiveDataAsync(Receive);
- DisconnectCalledByUser = false;
- break;
- }
+ if (clientSocketStatus != SocketStatus.SOCKET_STATUS_CONNECTED)
+ {
+ Debug.Console(0, this, "Socket status change {0} ({1})", clientSocketStatus, ClientStatusText);
+ WaitAndTryReconnect();
+ }
+ else
+ {
+ Debug.Console(1, this, "Socket status change {0} ({1})", clientSocketStatus, ClientStatusText);
+ _client.ReceiveDataAsync(Receive);
+ }
var handler = ConnectionChange;
if (handler != null)
ConnectionChange(this, new GenericSocketStatusChageEventArgs(this));
-
- // Relay the event
- //var handler = SocketStatusChange;
- //if (handler != null)
- // SocketStatusChange(this);
}
}
@@ -519,4 +563,4 @@ namespace PepperDash.Core
}
-}
\ No newline at end of file
+}
diff --git a/Pepperdash Core/Pepperdash Core/Logging/Debug.cs b/Pepperdash Core/Pepperdash Core/Logging/Debug.cs
index ee51b2c..1a84968 100644
--- a/Pepperdash Core/Pepperdash Core/Logging/Debug.cs
+++ b/Pepperdash Core/Pepperdash Core/Logging/Debug.cs
@@ -410,7 +410,10 @@ namespace PepperDash.Core
string format, params object[] items)
{
var str = string.Format("[{0}] {1}", dev.Key, string.Format(format, items));
- LogError(errorLogLevel, str);
+ if (errorLogLevel != ErrorLogLevel.None)
+ {
+ LogError(errorLogLevel, str);
+ }
if (Level >= level)
{
Console(level, str);
@@ -424,7 +427,10 @@ namespace PepperDash.Core
string format, params object[] items)
{
var str = string.Format(format, items);
- LogError(errorLogLevel, str);
+ if (errorLogLevel != ErrorLogLevel.None)
+ {
+ LogError(errorLogLevel, str);
+ }
if (Level >= level)
{
Console(level, str);
@@ -566,6 +572,7 @@ namespace PepperDash.Core
String.Format(
@"Debug settings file migration not necessary. Using file at \user\debugSettings\program{0}",
InitialParametersClass.ApplicationNumber));
+
return;
}