diff --git a/Pepperdash Core/Pepperdash Core.suo b/Pepperdash Core/Pepperdash Core.suo index 9d55ea5..185d585 100644 Binary files a/Pepperdash Core/Pepperdash Core.suo and b/Pepperdash Core/Pepperdash Core.suo differ diff --git a/Pepperdash Core/Pepperdash Core/Comm/DynamicTCPClient.cs b/Pepperdash Core/Pepperdash Core/Comm/DynamicTCPClient.cs deleted file mode 100644 index 08b6ba8..0000000 --- a/Pepperdash Core/Pepperdash Core/Comm/DynamicTCPClient.cs +++ /dev/null @@ -1,371 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Text.RegularExpressions; -using Crestron.SimplSharp; -using Crestron.SimplSharp.CrestronSockets; -using PepperDash.Core; - -namespace PepperDash.Core -{ - public class DynamicTcpClient : Device, ISocketStatus, IAutoReconnect - { - #region Events - - public event EventHandler BytesReceived; - - public event EventHandler TextReceived; - - public event EventHandler ConnectionChange; - - #endregion - - #region Properties & Variables - /// - /// Address of server - /// - public string Hostname { get; set; } - - /// - /// Port on server - /// - public int Port { get; set; } - - /// - /// S+ helper - /// - public ushort UPort - { - get { return Convert.ToUInt16(Port); } - set { Port = Convert.ToInt32(value); } - } - - /// - /// Bool to show whether the server requires a preshared key. This is used in the DynamicTCPServer class - /// - public bool RequiresPresharedKey { get; set; } - - /// - /// S+ helper for requires shared key bool - /// - public ushort uRequiresPresharedKey - { - set - { - if (value == 1) - RequiresPresharedKey = true; - else - RequiresPresharedKey = false; - } - } - - /// - /// SharedKey is sent for varification to the server. Shared key can be any text (255 char limit in SIMPL+ Module), but must match the Shared Key on the Server module - /// - public string SharedKey { get; set; } - - /// - /// flag to show the client is waiting for the server to send the shared key - /// - private bool WaitingForSharedKeyResponse { get; set; } - - /// - /// Defaults to 2000 - /// - public int BufferSize { get; set; } - - /// - /// Bool showing if socket is connected - /// - public bool IsConnected - { - get { return Client != null && Client.ClientStatus == SocketStatus.SOCKET_STATUS_CONNECTED; } - } - - /// - /// S+ helper for IsConnected - /// - public ushort UIsConnected - { - get { return (ushort)(IsConnected ? 1 : 0); } - } - - /// - /// Client socket status Read only - /// - public SocketStatus ClientStatus - { - get - { - if (Client == null) - return SocketStatus.SOCKET_STATUS_NO_CONNECT; - return Client.ClientStatus; - } - } - - /// - /// Contains the familiar Simpl analog status values. This drives the ConnectionChange event - /// and IsConnected would be true when this == 2. - /// - public ushort UStatus - { - get { return (ushort)ClientStatus; } - } - - /// - /// Status text shows the message associated with socket status - /// - public string ClientStatusText { get { return ClientStatus.ToString(); } } - - /// - /// bool to track if auto reconnect should be set on the socket - /// - public bool AutoReconnect { get; set; } - - /// - /// S+ helper for AutoReconnect - /// - public ushort UAutoReconnect - { - 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; } - - /// - /// Flag Set only when the disconnect method is called. - /// - bool DisconnectCalledByUser; - - /// - /// Connected bool - /// - public bool Connected - { - get { return Client.ClientStatus == SocketStatus.SOCKET_STATUS_CONNECTED; } - } - - CTimer RetryTimer; //private Timer for auto reconnect - - public SecureTCPClient Client; //Secure Client Class - - #endregion - - #region Constructors - - //Base class constructor - public DynamicTcpClient(string key, string address, int port, int bufferSize) - : base(key) - { - Hostname = address; - Port = port; - BufferSize = bufferSize; - AutoReconnectIntervalMs = 5000; - } - - //base class constructor - public DynamicTcpClient() - : base("Uninitialized SecureTcpClient") - { - CrestronEnvironment.ProgramStatusEventHandler += new ProgramStatusEventHandler(CrestronEnvironment_ProgramStatusEventHandler); - AutoReconnectIntervalMs = 5000; - BufferSize = 2000; - } - #endregion - - #region Methods - /// - /// Just to help S+ set the key - /// - public void Initialize(string key) - { - Key = key; - } - - /// - /// Handles closing this up when the program shuts down - /// - void CrestronEnvironment_ProgramStatusEventHandler(eProgramStatusEventType programEventType) - { - if (programEventType == eProgramStatusEventType.Stopping) - { - if (Client != null) - { - Debug.Console(1, this, "Program stopping. Closing connection"); - Client.DisconnectFromServer(); - Client.Dispose(); - } - } - } - - /// - /// Deactivate the client. Unregisters the socket status change event and returns true. - /// - /// - public override bool Deactivate() - { - if(Client != null) - Client.SocketStatusChange -= this.Client_SocketStatusChange; - return true; - } - - /// - /// Connect Method. Will return if already connected. Will write errors if missing address, port, or unique key/name. - /// - public void Connect() - { - if (IsConnected) - return; - - if (string.IsNullOrEmpty(Hostname)) - { - Debug.Console(1, Debug.ErrorLogLevel.Warning, "GenericSecureTcpClient '{0}': No address set", Key); - ErrorLog.Warn(string.Format("GenericSecureTcpClient '{0}': No address set", Key)); - return; - } - if (Port < 1 || Port > 65535) - { - Debug.Console(1, Debug.ErrorLogLevel.Warning, "GenericSecureTcpClient '{0}': Invalid port", Key); - ErrorLog.Warn(string.Format("GenericSecureTcpClient '{0}': Invalid port", Key)); - return; - } - if (string.IsNullOrEmpty(SharedKey) && RequiresPresharedKey) - { - Debug.Console(1, Debug.ErrorLogLevel.Warning, "GenericSecureTcpClient '{0}': No Shared Key set", Key); - ErrorLog.Warn(string.Format("GenericSecureTcpClient '{0}': No Shared Key set", Key)); - return; - } - Client = new SecureTCPClient(Hostname, Port, BufferSize); - Client.SocketStatusChange += Client_SocketStatusChange; - try - { - DisconnectCalledByUser = false; - if(RequiresPresharedKey) - WaitingForSharedKeyResponse = true; - SocketErrorCodes error = Client.ConnectToServer(); - } - catch (Exception ex) - { - CrestronConsole.PrintLine("Secure Client could not connect. Error: {0}", ex.Message); - } - } - - /// - /// Disconnect client. Does not dispose. - /// - public void Disconnect() - { - DisconnectCalledByUser = true; - Client.DisconnectFromServer(); - } - - /// - /// callback after connection made - /// - /// - void ConnectToServerCallback(object o) - { - Client.ConnectToServer(); - if (Client.ClientStatus != SocketStatus.SOCKET_STATUS_CONNECTED) - WaitAndTryReconnect(); - } - - /// - /// Called from Socket Status change if auto reconnect and socket disconnected (Not disconnected by user) - /// - void WaitAndTryReconnect() - { - Client.DisconnectFromServer(); - Debug.Console(2, "Attempting reconnect, status={0}", Client.ClientStatus); - RetryTimer = new CTimer(ConnectToServerCallback, AutoReconnectIntervalMs); - } - - /// - /// Receive callback - /// - /// - /// - void Receive(SecureTCPClient client, int numBytes) - { - if (numBytes > 0) - { - var bytes = client.IncomingDataBuffer.Take(numBytes).ToArray(); - var str = Encoding.GetEncoding(28591).GetString(bytes, 0, bytes.Length); - if (WaitingForSharedKeyResponse && RequiresPresharedKey) - { - if (str != (SharedKey + "\n")) - { - WaitingForSharedKeyResponse = false; - Client.DisconnectFromServer(); - CrestronConsole.PrintLine("Client {0} was disconnected from server because the server did not respond with a matching shared key after connection", Key); - ErrorLog.Error("Client {0} was disconnected from server because the server did not respond with a matching shared key after connection", Key); - return; - } - else - { - WaitingForSharedKeyResponse = false; - CrestronConsole.PrintLine("Client {0} successfully connected to the server and received the Shared Key. Ready for communication", Key); - } - } - else - { - var bytesHandler = BytesReceived; - if (bytesHandler != null) - bytesHandler(this, new GenericCommMethodReceiveBytesArgs(bytes)); - var textHandler = TextReceived; - if (textHandler != null) - { - - textHandler(this, new GenericCommMethodReceiveTextArgs(str)); - } - } - } - Client.ReceiveDataAsync(Receive); - } - - /// - /// General send method - /// - public void SendText(string text) - { - var bytes = Encoding.GetEncoding(28591).GetBytes(text); - Client.SendData(bytes, bytes.Length); - } - - public void SendBytes(byte[] bytes) - { - Client.SendData(bytes, bytes.Length); - } - - /// - /// SocketStatusChange Callback - /// - /// - /// - void Client_SocketStatusChange(SecureTCPClient client, SocketStatus clientSocketStatus) - { - Debug.Console(2, 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); - SendText(SharedKey + "\n"); - DisconnectCalledByUser = false; - break; - } - - var handler = ConnectionChange; - if (handler != null) - ConnectionChange(this, new GenericSocketStatusChageEventArgs(this)); - } - #endregion - } -} \ No newline at end of file diff --git a/Pepperdash Core/Pepperdash Core/Comm/DynamicTCPServer.cs b/Pepperdash Core/Pepperdash Core/Comm/DynamicTCPServer.cs deleted file mode 100644 index 7a9765d..0000000 --- a/Pepperdash Core/Pepperdash Core/Comm/DynamicTCPServer.cs +++ /dev/null @@ -1,501 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using Crestron.SimplSharp; -using Crestron.SimplSharp.CrestronSockets; -using PepperDash.Core; - -namespace PepperDash.Core -{ - public class DynamicTCPServer : Device - { - #region Events - public event EventHandler TextReceived; - - public event EventHandler ClientConnectionChange; - - public event EventHandler ServerStateChange; - #endregion - - #region Properties/Variables - /// - /// Secure or unsecure TCP server. Defaults to Unsecure or standard TCP server without SSL - /// - public bool Secure { get; set; } - - /// - /// S+ Helper for Secure bool. Parameter in SIMPL+ so there is no get, one way set from simpl+ Param to property in func main of SIMPL+ - /// - public ushort uSecure - { - set - { - if (value == 1) - Secure = true; - else if (value == 0) - Secure = false; - } - } - - public string status - { - get - { - if (Secure ? SecureServer != null : UnsecureServer != null) - return Secure ? SecureServer.State.ToString() : UnsecureServer.State.ToString(); - else - return ""; - } - - } - - /// - /// Bool showing if socket is connected - /// - public bool IsConnected - { - get { return (Secure ? SecureServer != null : UnsecureServer != null) && - (Secure ? SecureServer.State == ServerState.SERVER_CONNECTED : UnsecureServer.State == ServerState.SERVER_CONNECTED); } - } - - /// - /// S+ helper for IsConnected - /// - public ushort uIsConnected - { - get { return (ushort)(IsConnected ? 1 : 0); } - } - - /// - /// Bool showing if socket is connected - /// - public bool IsListening - { - get { return (Secure ? SecureServer != null : UnsecureServer != null) && - (Secure ? SecureServer.State == ServerState.SERVER_LISTENING : UnsecureServer.State == ServerState.SERVER_LISTENING); } - } - - /// - /// S+ helper for IsConnected - /// - public ushort uIsListening - { - get { return (ushort)(IsListening ? 1 : 0); } - } - - public ushort MaxClients { get; set; } // should be set by parameter in SIMPL+ in the MAIN method, Should not ever need to be configurable - /// - /// Number of clients currently connected. - /// - public ushort NumberOfClientsConnected - { - get - { - if (Secure ? SecureServer != null : UnsecureServer != null) - return Secure ? (ushort)SecureServer.NumberOfClientsConnected : (ushort)UnsecureServer.NumberOfClientsConnected; - return 0; - } - } - - /// - /// Port on server - /// - public int Port { get; set; } - - /// - /// S+ helper - /// - public ushort uPort - { - get { return Convert.ToUInt16(Port); } - set { Port = Convert.ToInt32(value); } - } - - /// - /// Bool to show whether the server requires a preshared key. Must be set the same in the client, and if true shared keys must be identical on server/client - /// - public bool RequiresPresharedKey { get; set; } - - /// - /// S+ helper for requires shared key bool - /// - public ushort uRequiresPresharedKey - { - set - { - if (value == 1) - RequiresPresharedKey = true; - else - RequiresPresharedKey = false; - } - } - - /// - /// SharedKey is sent for varification to the server. Shared key can be any text (255 char limit in SIMPL+ Module), but must match the Shared Key on the Server module. - /// If SharedKey changes while server is listening or clients are connected, disconnect and stop listening will be called - /// - public string SharedKey { get; set; } - - /// - /// flags to show the secure server is waiting for client at index to send the shared key - /// - public List WaitingForSharedKey = new List(); - - /// - /// Store the connected client indexes - /// - public List ConnectedClientsIndexes = new List(); - - - /// - /// Defaults to 2000 - /// - public int BufferSize { get; set; } - - public string OnlyAcceptConnectionFromAddress { get; set; } - - private bool ServerStopped { get; set; } - - SecureTCPServer SecureServer; - TCPServer UnsecureServer; - - #endregion - - #region Constructors - //base class constructor - public DynamicTCPServer() - : base("Uninitialized Dynamic TCP Server") - { - CrestronEnvironment.ProgramStatusEventHandler += new ProgramStatusEventHandler(CrestronEnvironment_ProgramStatusEventHandler); - BufferSize = 2000; - Secure = false; - } - #endregion - - #region Methods - Server Actions - public void Initialize(string key) - { - Key = key; - } - - public void Listen() - { - try - { - if (Port < 1 || Port > 65535) - { - Debug.Console(1, Debug.ErrorLogLevel.Warning, "GenericSecureTcpClient '{0}': Invalid port", Key); - ErrorLog.Warn(string.Format("GenericSecureTcpClient '{0}': Invalid port", Key)); - return; - } - if (string.IsNullOrEmpty(SharedKey) && RequiresPresharedKey) - { - Debug.Console(1, Debug.ErrorLogLevel.Warning, "GenericSecureTcpClient '{0}': No Shared Key set", Key); - ErrorLog.Warn(string.Format("GenericSecureTcpClient '{0}': No Shared Key set", Key)); - return; - } - if (IsListening) - return; - if (Secure) - { - SecureServer = new SecureTCPServer(Port, MaxClients); - SecureServer.SocketStatusChange += new SecureTCPServerSocketStatusChangeEventHandler(SecureServer_SocketStatusChange); - ServerStopped = false; - if (!string.IsNullOrEmpty(OnlyAcceptConnectionFromAddress)) - SecureServer.WaitForConnectionAsync(OnlyAcceptConnectionFromAddress, SecureConnectCallback); - else - SecureServer.WaitForConnectionAsync(IPAddress.Any, SecureConnectCallback); - onServerStateChange(); - Debug.Console(2, "Secure Server Status: {0}, Socket Status: {1}\r\n", SecureServer.State.ToString(), SecureServer.ServerSocketStatus); - } - else - { - UnsecureServer = new TCPServer(Port, MaxClients); - UnsecureServer.SocketStatusChange += new TCPServerSocketStatusChangeEventHandler(UnsecureServer_SocketStatusChange); - ServerStopped = false; - if (!string.IsNullOrEmpty(OnlyAcceptConnectionFromAddress)) - UnsecureServer.WaitForConnectionAsync(OnlyAcceptConnectionFromAddress, UnsecureConnectCallback); - else - UnsecureServer.WaitForConnectionAsync(IPAddress.Any, UnsecureConnectCallback); - onServerStateChange(); - Debug.Console(2, "Unsecure Server Status: {0}, Socket Status: {1}\r\n", UnsecureServer.State.ToString(), UnsecureServer.ServerSocketStatus); - } - } - catch (Exception ex) - { - ErrorLog.Error("Error with Dynamic Server: {0}", ex.ToString()); - } - } - - public void StopListening() - { - Debug.Console(2, "Stopping Listener"); - if (SecureServer != null) - SecureServer.Stop(); - if (UnsecureServer != null) - UnsecureServer.Stop(); - ServerStopped = true; - onServerStateChange(); - } - - public void DisconnectAllClients() - { - Debug.Console(2, "Disconnecting All Clients"); - if (SecureServer != null) - SecureServer.DisconnectAll(); - if (UnsecureServer != null) - UnsecureServer.DisconnectAll(); - onConnectionChange(); - onServerStateChange(); //State shows both listening and connected - } - - public void BroadcastText(string text) - { - if (ConnectedClientsIndexes.Count > 0) - { - if (Secure) - { - foreach (uint i in ConnectedClientsIndexes) - { - byte[] b = Encoding.GetEncoding(28591).GetBytes(text); - SecureServer.SendDataAsync(i, b, b.Length, SecureSendDataAsyncCallback); - } - } - else - { - foreach (uint i in ConnectedClientsIndexes) - { - byte[] b = Encoding.GetEncoding(28591).GetBytes(text); - UnsecureServer.SendDataAsync(i, b, b.Length, UnsecureSendDataAsyncCallback); - } - } - } - } - - /// - /// Not sure this is useful in library, maybe Pro?? - /// - /// - /// - public void SendTextToClient(string text, uint clientIndex) - { - if (Secure) - { - byte[] b = Encoding.GetEncoding(28591).GetBytes(text); - SecureServer.SendDataAsync(clientIndex, b, b.Length, SecureSendDataAsyncCallback); - } - else - { - byte[] b = Encoding.GetEncoding(28591).GetBytes(text); - UnsecureServer.SendDataAsync(clientIndex, b, b.Length, UnsecureSendDataAsyncCallback); - } - } - #endregion - - #region Methods - Socket Status Changed Callbacks - void SecureServer_SocketStatusChange(SecureTCPServer mySecureTCPServer, uint clientIndex, SocketStatus serverSocketStatus) - { - Debug.Console(2, "Client at {0} ServerSocketStatus {1}", - mySecureTCPServer.GetAddressServerAcceptedConnectionFromForSpecificClient(clientIndex), serverSocketStatus.ToString()); - if (mySecureTCPServer.GetServerSocketStatusForSpecificClient(clientIndex) == SocketStatus.SOCKET_STATUS_CONNECTED) - { - if (RequiresPresharedKey && !WaitingForSharedKey.Contains(clientIndex)) - WaitingForSharedKey.Add(clientIndex); - if (!ConnectedClientsIndexes.Contains(clientIndex)) - ConnectedClientsIndexes.Add(clientIndex); - } - if (mySecureTCPServer.GetServerSocketStatusForSpecificClient(clientIndex) != SocketStatus.SOCKET_STATUS_CONNECTED && ConnectedClientsIndexes.Contains(clientIndex)) - ConnectedClientsIndexes.Remove(clientIndex); - - onConnectionChange();//Go to simpl and send the server and whether it is secure or not. Could check secure from Simpl+ but better to use the passed - //variable in case we need to use this in Pro. Simpl+ won't use arguments, will just check the uIsConnected Property. Currently Simpl+ is just going to report - //connected not reporting by client - } - - void UnsecureServer_SocketStatusChange(TCPServer mySecureTCPServer, uint clientIndex, SocketStatus serverSocketStatus) - { - Debug.Console(2, "Client at {0} ServerSocketStatus {1}", - mySecureTCPServer.GetAddressServerAcceptedConnectionFromForSpecificClient(clientIndex), serverSocketStatus.ToString()); - if (mySecureTCPServer.GetServerSocketStatusForSpecificClient(clientIndex) == SocketStatus.SOCKET_STATUS_CONNECTED) - { - if (RequiresPresharedKey && !WaitingForSharedKey.Contains(clientIndex)) - WaitingForSharedKey.Add(clientIndex); - if (!ConnectedClientsIndexes.Contains(clientIndex)) - ConnectedClientsIndexes.Add(clientIndex); - } - if (mySecureTCPServer.GetServerSocketStatusForSpecificClient(clientIndex) != SocketStatus.SOCKET_STATUS_CONNECTED && ConnectedClientsIndexes.Contains(clientIndex)) - ConnectedClientsIndexes.Remove(clientIndex); - - onConnectionChange(); - } - #endregion - - #region Methods Connected Callbacks - void SecureConnectCallback(SecureTCPServer mySecureTCPServer, uint clientIndex) - { - if (mySecureTCPServer.ClientConnected(clientIndex)) - { - if (RequiresPresharedKey) - { - byte[] b = Encoding.GetEncoding(28591).GetBytes(SharedKey + "\n"); - mySecureTCPServer.SendDataAsync(clientIndex, b, b.Length, SecureSendDataAsyncCallback); - Debug.Console(2, "Sent Shared Key to client at {0}", mySecureTCPServer.GetAddressServerAcceptedConnectionFromForSpecificClient(clientIndex)); - } - mySecureTCPServer.ReceiveDataAsync(clientIndex, SecureReceivedCallback); - if (mySecureTCPServer.State != ServerState.SERVER_LISTENING && MaxClients > 1 && !ServerStopped) - mySecureTCPServer.WaitForConnectionAsync(IPAddress.Any, SecureConnectCallback); - } - } - - void UnsecureConnectCallback(TCPServer myTCPServer, uint clientIndex) - { - if (myTCPServer.ClientConnected(clientIndex)) - { - if (RequiresPresharedKey) - { - byte[] b = Encoding.GetEncoding(28591).GetBytes(SharedKey + "\n"); - myTCPServer.SendDataAsync(clientIndex, b, b.Length, UnsecureSendDataAsyncCallback); - Debug.Console(2, "Sent Shared Key to client at {0}", myTCPServer.GetAddressServerAcceptedConnectionFromForSpecificClient(clientIndex)); - } - myTCPServer.ReceiveDataAsync(clientIndex, UnsecureReceivedCallback); - if (myTCPServer.State != ServerState.SERVER_LISTENING && MaxClients > 1 && !ServerStopped) - myTCPServer.WaitForConnectionAsync(IPAddress.Any, UnsecureConnectCallback); - } - if (myTCPServer.State != ServerState.SERVER_LISTENING && MaxClients > 1 && !ServerStopped) - myTCPServer.WaitForConnectionAsync(IPAddress.Any, UnsecureConnectCallback); - } - #endregion - - #region Methods - Send/Receive Callbacks - void SecureSendDataAsyncCallback(SecureTCPServer mySecureTCPServer, uint clientIndex, int numberOfBytesSent) - { - //Seems there is nothing to do here - } - - void UnsecureSendDataAsyncCallback(TCPServer myTCPServer, uint clientIndex, int numberOfBytesSent) - { - //Seems there is nothing to do here - } - - void SecureReceivedCallback(SecureTCPServer mySecureTCPServer, uint clientIndex, int numberOfBytesReceived) - { - if (numberOfBytesReceived > 0) - { - string received = "Nothing"; - byte[] bytes = mySecureTCPServer.GetIncomingDataBufferForSpecificClient(clientIndex); - received = System.Text.Encoding.GetEncoding(28591).GetString(bytes, 0, numberOfBytesReceived); - if (WaitingForSharedKey.Contains(clientIndex)) - { - received = received.Replace("\r", ""); - received = received.Replace("\n", ""); - if (received != SharedKey) - { - byte[] b = Encoding.GetEncoding(28591).GetBytes("Shared key did not match server. Disconnecting"); - Debug.Console(2, "Client at index {0} Shared key did not match the server, disconnecting client", clientIndex); - ErrorLog.Error("Client at index {0} Shared key did not match the server, disconnecting client", clientIndex); - mySecureTCPServer.SendDataAsync(clientIndex, b, b.Length, null); - mySecureTCPServer.Disconnect(clientIndex); - } - if (mySecureTCPServer.NumberOfClientsConnected > 0) - mySecureTCPServer.ReceiveDataAsync(SecureReceivedCallback); - WaitingForSharedKey.Remove(clientIndex); - byte[] skResponse = Encoding.GetEncoding(28591).GetBytes("Shared Key Match, Connected and ready for communication"); - mySecureTCPServer.SendDataAsync(clientIndex, skResponse, skResponse.Length, null); - mySecureTCPServer.ReceiveDataAsync(SecureReceivedCallback); - } - else - { - mySecureTCPServer.ReceiveDataAsync(SecureReceivedCallback); - Debug.Console(2, "Secure Server Listening on Port: {0}, client IP: {1}, NumberOfBytesReceived: {2}, Received: {3}\r\n", - mySecureTCPServer.PortNumber, mySecureTCPServer.AddressServerAcceptedConnectionFrom, numberOfBytesReceived, received); - onTextReceived(received); - } - } - if (mySecureTCPServer.GetServerSocketStatusForSpecificClient(clientIndex) == SocketStatus.SOCKET_STATUS_CONNECTED) - mySecureTCPServer.ReceiveDataAsync(clientIndex, SecureReceivedCallback); - } - - void UnsecureReceivedCallback(TCPServer myTCPServer, uint clientIndex, int numberOfBytesReceived) - { - if (numberOfBytesReceived > 0) - { - string received = "Nothing"; - byte[] bytes = myTCPServer.GetIncomingDataBufferForSpecificClient(clientIndex); - received = System.Text.Encoding.GetEncoding(28591).GetString(bytes, 0, numberOfBytesReceived); - if (WaitingForSharedKey.Contains(clientIndex)) - { - received = received.Replace("\r", ""); - received = received.Replace("\n", ""); - if (received != SharedKey) - { - byte[] b = Encoding.GetEncoding(28591).GetBytes("Shared key did not match server. Disconnecting"); - Debug.Console(2, "Client at index {0} Shared key did not match the server, disconnecting client", clientIndex); - ErrorLog.Error("Client at index {0} Shared key did not match the server, disconnecting client", clientIndex); - myTCPServer.SendDataAsync(clientIndex, b, b.Length, null); - myTCPServer.Disconnect(clientIndex); - } - if (myTCPServer.NumberOfClientsConnected > 0) - myTCPServer.ReceiveDataAsync(UnsecureReceivedCallback); - WaitingForSharedKey.Remove(clientIndex); - byte[] skResponse = Encoding.GetEncoding(28591).GetBytes("Shared Key Match, Connected and ready for communication"); - myTCPServer.SendDataAsync(clientIndex, skResponse, skResponse.Length, null); - myTCPServer.ReceiveDataAsync(UnsecureReceivedCallback); - } - else - { - myTCPServer.ReceiveDataAsync(UnsecureReceivedCallback); - Debug.Console(2, "Secure Server Listening on Port: {0}, client IP: {1}, NumberOfBytesReceived: {2}, Received: {3}\r\n", - myTCPServer.PortNumber, myTCPServer.AddressServerAcceptedConnectionFrom, numberOfBytesReceived, received); - onTextReceived(received); - } - } - if (myTCPServer.GetServerSocketStatusForSpecificClient(clientIndex) == SocketStatus.SOCKET_STATUS_CONNECTED) - myTCPServer.ReceiveDataAsync(clientIndex, UnsecureReceivedCallback); - } - #endregion - - #region Methods - EventHelpers/Callbacks - void onConnectionChange() - { - var handler = ClientConnectionChange; - if (handler != null) - { - if (Secure) - handler(this, new DynamicTCPServerSocketStatusChangeEventArgs(SecureServer, Secure)); - else - handler(this, new DynamicTCPServerSocketStatusChangeEventArgs(UnsecureServer, Secure)); - } - } - - void onTextReceived(string text) - { - var handler = TextReceived; - if (handler != null) - handler(this, new GenericCommMethodReceiveTextArgs(text)); - } - - void onServerStateChange() - { - var handler = ServerStateChange; - if(handler != null) - { - if(Secure) - handler(this, new DynamicTCPServerStateChangedEventArgs(SecureServer, Secure)); - else - handler(this, new DynamicTCPServerStateChangedEventArgs(UnsecureServer, Secure)); - } - } - - void CrestronEnvironment_ProgramStatusEventHandler(eProgramStatusEventType programEventType) - { - if (programEventType == eProgramStatusEventType.Stopping) - { - Debug.Console(1, this, "Program stopping. Closing server"); - DisconnectAllClients(); - StopListening(); - } - } - #endregion - } -} \ No newline at end of file diff --git a/Pepperdash Core/Pepperdash Core/Comm/GenericSecureTcpClient.cs b/Pepperdash Core/Pepperdash Core/Comm/GenericSecureTcpClient.cs deleted file mode 100644 index 3177fcf..0000000 --- a/Pepperdash Core/Pepperdash Core/Comm/GenericSecureTcpClient.cs +++ /dev/null @@ -1,372 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Text.RegularExpressions; -using Crestron.SimplSharp; -using Crestron.SimplSharp.CrestronSockets; -using PepperDash.Core; - -namespace PepperDash.Core -{ - public class GenericSecureTcpClient : Device, ISocketStatus, IAutoReconnect - { - #region Events - - public event EventHandler BytesReceived; - - public event EventHandler TextReceived; - - public event EventHandler ConnectionChange; - - #endregion - - #region Properties & Variables - /// - /// Address of server - /// - public string Hostname { get; set; } - - /// - /// Port on server - /// - public int Port { get; set; } - - /// - /// S+ helper - /// - public ushort UPort - { - get { return Convert.ToUInt16(Port); } - set { Port = Convert.ToInt32(value); } - } - - /// - /// Bool to show whether the server requires a preshared key. This is used in the DynamicTCPServer class - /// - public bool RequiresPresharedKey { get; set; } - - /// - /// S+ helper for requires shared key bool - /// - public ushort URequiresPresharedKey - { - set - { - if (value == 1) - RequiresPresharedKey = true; - else - RequiresPresharedKey = false; - } - } - - /// - /// SharedKey is sent for varification to the server. Shared key can be any text (255 char limit in SIMPL+ Module), but must match the Shared Key on the Server module - /// - public string SharedKey { get; set; } - - /// - /// flag to show the client is waiting for the server to send the shared key - /// - private bool WaitingForSharedKeyResponse { get; set; } - - /// - /// Defaults to 2000 - /// - public int BufferSize { get; set; } - - /// - /// Bool showing if socket is connected - /// - public bool IsConnected - { - get { return Client != null && Client.ClientStatus == SocketStatus.SOCKET_STATUS_CONNECTED; } - } - - /// - /// S+ helper for IsConnected - /// - public ushort UIsConnected - { - get { return (ushort)(IsConnected ? 1 : 0); } - } - - /// - /// Client socket status Read only - /// - public SocketStatus ClientStatus - { - get - { - if (Client == null) - return SocketStatus.SOCKET_STATUS_NO_CONNECT; - return Client.ClientStatus; - } - } - - /// - /// Contains the familiar Simpl analog status values. This drives the ConnectionChange event - /// and IsConnected would be true when this == 2. - /// - public ushort UStatus - { - get { return (ushort)ClientStatus; } - } - - /// - /// Status text shows the message associated with socket status - /// - public string ClientStatusText { get { return ClientStatus.ToString(); } } - - /// - /// bool to track if auto reconnect should be set on the socket - /// - public bool AutoReconnect { get; set; } - - /// - /// S+ helper for AutoReconnect - /// - public ushort UAutoReconnect - { - 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; } - - /// - /// Flag Set only when the disconnect method is called. - /// - bool DisconnectCalledByUser; - - /// - /// Connected bool - /// - public bool Connected - { - get { return Client.ClientStatus == SocketStatus.SOCKET_STATUS_CONNECTED; } - } - - CTimer RetryTimer; //private Timer for auto reconnect - - public SecureTCPClient Client; //Secure Client Class - - #endregion - - #region Constructors - - //Base class constructor - public GenericSecureTcpClient(string key, string address, int port, int bufferSize) - : base(key) - { - Hostname = address; - Port = port; - BufferSize = bufferSize; - AutoReconnectIntervalMs = 5000; - } - - //base class constructor - public GenericSecureTcpClient() - : base("Uninitialized SecureTcpClient") - { - CrestronEnvironment.ProgramStatusEventHandler += new ProgramStatusEventHandler(CrestronEnvironment_ProgramStatusEventHandler); - AutoReconnectIntervalMs = 5000; - BufferSize = 2000; - } - #endregion - - #region Methods - /// - /// Just to help S+ set the key - /// - public void Initialize(string key) - { - Key = key; - } - - /// - /// Handles closing this up when the program shuts down - /// - void CrestronEnvironment_ProgramStatusEventHandler(eProgramStatusEventType programEventType) - { - if (programEventType == eProgramStatusEventType.Stopping) - { - if (Client != null) - { - Debug.Console(1, this, "Program stopping. Closing connection"); - Client.DisconnectFromServer(); - Client.Dispose(); - } - } - } - - /// - /// Deactivate the client. Unregisters the socket status change event and returns true. - /// - /// - public override bool Deactivate() - { - if(Client != null) - Client.SocketStatusChange -= this.Client_SocketStatusChange; - return true; - } - - /// - /// Connect Method. Will return if already connected. Will write errors if missing address, port, or unique key/name. - /// - public void Connect() - { - if (IsConnected) - return; - - if (string.IsNullOrEmpty(Hostname)) - { - Debug.Console(1, Debug.ErrorLogLevel.Warning, "GenericSecureTcpClient '{0}': No address set", Key); - ErrorLog.Warn(string.Format("GenericSecureTcpClient '{0}': No address set", Key)); - return; - } - if (Port < 1 || Port > 65535) - { - Debug.Console(1, Debug.ErrorLogLevel.Warning, "GenericSecureTcpClient '{0}': Invalid port", Key); - ErrorLog.Warn(string.Format("GenericSecureTcpClient '{0}': Invalid port", Key)); - return; - } - if (string.IsNullOrEmpty(SharedKey) && RequiresPresharedKey) - { - Debug.Console(1, Debug.ErrorLogLevel.Warning, "GenericSecureTcpClient '{0}': No Shared Key set", Key); - ErrorLog.Warn(string.Format("GenericSecureTcpClient '{0}': No Shared Key set", Key)); - return; - } - Client = new SecureTCPClient(Hostname, Port, BufferSize); - Client.SocketStatusChange += Client_SocketStatusChange; - try - { - DisconnectCalledByUser = false; - if(RequiresPresharedKey) - WaitingForSharedKeyResponse = true; - SocketErrorCodes error = Client.ConnectToServer(); - } - catch (Exception ex) - { - CrestronConsole.PrintLine("Secure Client could not connect. Error: {0}", ex.Message); - } - } - - /// - /// Disconnect client. Does not dispose. - /// - public void Disconnect() - { - DisconnectCalledByUser = true; - Client.DisconnectFromServer(); - } - - /// - /// callback after connection made - /// - /// - void ConnectToServerCallback(object o) - { - Client.ConnectToServer(); - if (Client.ClientStatus != SocketStatus.SOCKET_STATUS_CONNECTED) - WaitAndTryReconnect(); - } - - /// - /// Called from Socket Status change if auto reconnect and socket disconnected (Not disconnected by user) - /// - void WaitAndTryReconnect() - { - Client.DisconnectFromServer(); - Debug.Console(2, "Attempting reconnect, status={0}", Client.ClientStatus); - if(!DisconnectCalledByUser) - RetryTimer = new CTimer(ConnectToServerCallback, AutoReconnectIntervalMs); - } - - /// - /// Receive callback - /// - /// - /// - void Receive(SecureTCPClient client, int numBytes) - { - if (numBytes > 0) - { - var bytes = client.IncomingDataBuffer.Take(numBytes).ToArray(); - var str = Encoding.GetEncoding(28591).GetString(bytes, 0, bytes.Length); - if (WaitingForSharedKeyResponse && RequiresPresharedKey) - { - if (str != (SharedKey + "\n")) - { - WaitingForSharedKeyResponse = false; - Client.DisconnectFromServer(); - CrestronConsole.PrintLine("Client {0} was disconnected from server because the server did not respond with a matching shared key after connection", Key); - ErrorLog.Error("Client {0} was disconnected from server because the server did not respond with a matching shared key after connection", Key); - return; - } - else - { - WaitingForSharedKeyResponse = false; - CrestronConsole.PrintLine("Client {0} successfully connected to the server and received the Shared Key. Ready for communication", Key); - } - } - else - { - var bytesHandler = BytesReceived; - if (bytesHandler != null) - bytesHandler(this, new GenericCommMethodReceiveBytesArgs(bytes)); - var textHandler = TextReceived; - if (textHandler != null) - { - - textHandler(this, new GenericCommMethodReceiveTextArgs(str)); - } - } - } - Client.ReceiveDataAsync(Receive); - } - - /// - /// General send method - /// - public void SendText(string text) - { - var bytes = Encoding.GetEncoding(28591).GetBytes(text); - Client.SendData(bytes, bytes.Length); - } - - public void SendBytes(byte[] bytes) - { - Client.SendData(bytes, bytes.Length); - } - - /// - /// SocketStatusChange Callback - /// - /// - /// - void Client_SocketStatusChange(SecureTCPClient client, SocketStatus clientSocketStatus) - { - Debug.Console(2, 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); - SendText(SharedKey + "\n"); - DisconnectCalledByUser = false; - break; - } - - var handler = ConnectionChange; - if (handler != null) - ConnectionChange(this, new GenericSocketStatusChageEventArgs(this)); - } - #endregion - } -} \ No newline at end of file