/// <summary> /// Secure Server Socket Status Changed Callback /// </summary> /// <param name="mySecureTCPServer"></param> /// <param name="clientIndex"></param> /// <param name="serverSocketStatus"></param> void SecureServer_SocketStatusChange(SecureTCPServer server, uint clientIndex, SocketStatus serverSocketStatus) { Debug.Console(2, "Client at {0} ServerSocketStatus {1}", server.GetAddressServerAcceptedConnectionFromForSpecificClient(clientIndex), serverSocketStatus.ToString()); if (server.GetServerSocketStatusForSpecificClient(clientIndex) == SocketStatus.SOCKET_STATUS_CONNECTED) { if (SharedKeyRequired && !WaitingForSharedKey.Contains(clientIndex)) { WaitingForSharedKey.Add(clientIndex); } if (!ConnectedClientsIndexes.Contains(clientIndex)) { ConnectedClientsIndexes.Add(clientIndex); } } else { if (ConnectedClientsIndexes.Contains(clientIndex)) { ConnectedClientsIndexes.Remove(clientIndex); } if (HeartbeatRequired && HeartbeatTimerDictionary.ContainsKey(clientIndex)) { HeartbeatTimerDictionary.Remove(clientIndex); } } if (SecureServer.ServerSocketStatus.ToString() != Status) { onConnectionChange(); } }
/// <summary> /// Not sure this is useful in library, maybe Pro?? /// </summary> /// <param name="text"></param> /// <param name="clientIndex"></param> public void SendTextToClient(string text, uint clientIndex) { try { byte[] b = Encoding.GetEncoding(28591).GetBytes(text); if (SecureServer != null && SecureServer.GetServerSocketStatusForSpecificClient(clientIndex) == SocketStatus.SOCKET_STATUS_CONNECTED) { if (!SharedKeyRequired || (SharedKeyRequired && ClientReadyAfterKeyExchange.Contains(clientIndex))) { SecureServer.SendDataAsync(clientIndex, b, b.Length, (x, y, z) => { }); } } } catch (Exception ex) { Debug.Console(2, this, "Error sending text to client. Text: {1}. Error: {0}", ex.Message, text); } }
/// <summary> /// Secure Received Data Async Callback /// </summary> /// <param name="mySecureTCPServer"></param> /// <param name="clientIndex"></param> /// <param name="numberOfBytesReceived"></param> void SecureReceivedDataAsyncCallback(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(SecureReceivedDataAsyncCallback); } 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(SecureReceivedDataAsyncCallback); } else { mySecureTCPServer.ReceiveDataAsync(SecureReceivedDataAsyncCallback); Debug.Console(2, "Secure Server Listening on Port: {0}, client IP: {1}, NumberOfBytesReceived: {2}, Received: {3}\r\n", mySecureTCPServer.PortNumber, mySecureTCPServer.GetAddressServerAcceptedConnectionFromForSpecificClient(clientIndex), numberOfBytesReceived, received); onTextReceived(received); } checkHeartbeat(clientIndex, received); } if (mySecureTCPServer.GetServerSocketStatusForSpecificClient(clientIndex) == SocketStatus.SOCKET_STATUS_CONNECTED) { mySecureTCPServer.ReceiveDataAsync(clientIndex, SecureReceivedDataAsyncCallback); } }
/// <summary> /// Secure Server Socket Status Changed Callback /// </summary> /// <param name="mySecureTCPServer"></param> /// <param name="clientIndex"></param> /// <param name="serverSocketStatus"></param> void SecureServer_SocketStatusChange(SecureTCPServer server, uint clientIndex, SocketStatus serverSocketStatus) { try { // Debug.Console(1, this, Debug.ErrorLogLevel.Notice, "SecureServerSocketStatusChange Index:{0} status:{1} Port:{2} IP:{3}", clientIndex, serverSocketStatus, this.SecureServer.GetPortNumberServerAcceptedConnectionFromForSpecificClient(clientIndex), this.SecureServer.GetLocalAddressServerAcceptedConnectionFromForSpecificClient(clientIndex)); if (serverSocketStatus != SocketStatus.SOCKET_STATUS_CONNECTED) { Debug.Console(1, this, Debug.ErrorLogLevel.Notice, "SecureServerSocketStatusChange ConnectedCLients: {0} ServerState: {1} Port: {2}", SecureServer.NumberOfClientsConnected, SecureServer.State, SecureServer.PortNumber); if (ConnectedClientsIndexes.Contains(clientIndex)) { ConnectedClientsIndexes.Remove(clientIndex); } if (HeartbeatRequired && HeartbeatTimerDictionary.ContainsKey(clientIndex)) { HeartbeatTimerDictionary[clientIndex].Stop(); HeartbeatTimerDictionary[clientIndex].Dispose(); HeartbeatTimerDictionary.Remove(clientIndex); } if (ClientReadyAfterKeyExchange.Contains(clientIndex)) { ClientReadyAfterKeyExchange.Remove(clientIndex); } if (WaitingForSharedKey.Contains(clientIndex)) { WaitingForSharedKey.Remove(clientIndex); } if (SecureServer.MaxNumberOfClientSupported > SecureServer.NumberOfClientsConnected) { Listen(); } } } catch (Exception ex) { Debug.Console(2, this, Debug.ErrorLogLevel.Error, "Error in Socket Status Change Callback. Error: {0}", ex); } //Use a thread for this event so that the server state updates to listening while this event is processed. Listening must be added to the server state //after every client connection so that the server can check and see if it is at max clients. Due to this the event fires and server listening enum bit flag //is not set. Putting in a thread allows the state to update before this event processes so that the subscribers to this event get accurate isListening in the event. CrestronInvoke.BeginInvoke(o => onConnectionChange(clientIndex, server.GetServerSocketStatusForSpecificClient(clientIndex)), null); }
/// <summary> /// Secure Received Data Async Callback /// </summary> /// <param name="mySecureTCPServer"></param> /// <param name="clientIndex"></param> /// <param name="numberOfBytesReceived"></param> void SecureReceivedDataAsyncCallback(SecureTCPServer mySecureTCPServer, uint clientIndex, int numberOfBytesReceived) { if (numberOfBytesReceived > 0) { string received = "Nothing"; var handler = TextReceivedQueueInvoke; try { 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(1, this, Debug.ErrorLogLevel.Warning, "Client at index {0} Shared key did not match the server, disconnecting client. Key: {1}", clientIndex, received); mySecureTCPServer.SendData(clientIndex, b, b.Length); mySecureTCPServer.Disconnect(clientIndex); return; } WaitingForSharedKey.Remove(clientIndex); byte[] success = Encoding.GetEncoding(28591).GetBytes("Shared Key Match"); mySecureTCPServer.SendDataAsync(clientIndex, success, success.Length, null); OnServerClientReadyForCommunications(clientIndex); Debug.Console(1, this, Debug.ErrorLogLevel.Notice, "Client with index {0} provided the shared key and successfully connected to the server", clientIndex); } else if (!string.IsNullOrEmpty(checkHeartbeat(clientIndex, received))) { onTextReceived(received, clientIndex); if (handler != null) { MessageQueue.TryToEnqueue(new GenericTcpServerCommMethodReceiveTextArgs(received, clientIndex)); } } } catch (Exception ex) { Debug.Console(2, this, Debug.ErrorLogLevel.Error, "Error Receiving data: {0}. Error: {1}", received, ex); } if (mySecureTCPServer.GetServerSocketStatusForSpecificClient(clientIndex) == SocketStatus.SOCKET_STATUS_CONNECTED) { mySecureTCPServer.ReceiveDataAsync(clientIndex, SecureReceivedDataAsyncCallback); } //Check to see if there is a subscription to the TextReceivedQueueInvoke event. If there is start the dequeue thread. if (handler != null) { var gotLock = DequeueLock.TryEnter(); if (gotLock) { CrestronInvoke.BeginInvoke((o) => DequeueEvent()); } } } else { mySecureTCPServer.Disconnect(clientIndex); } }
/// <summary> /// Secure TCP Client Connected to Secure Server Callback /// </summary> /// <param name="mySecureTCPServer"></param> /// <param name="clientIndex"></param> void SecureConnectCallback(SecureTCPServer server, uint clientIndex) { try { Debug.Console(1, this, Debug.ErrorLogLevel.Notice, "ConnectCallback: IPAddress: {0}. Index: {1}. Status: {2}", server.GetAddressServerAcceptedConnectionFromForSpecificClient(clientIndex), clientIndex, server.GetServerSocketStatusForSpecificClient(clientIndex)); if (clientIndex != 0) { if (server.ClientConnected(clientIndex)) { if (!ConnectedClientsIndexes.Contains(clientIndex)) { ConnectedClientsIndexes.Add(clientIndex); } if (SharedKeyRequired) { if (!WaitingForSharedKey.Contains(clientIndex)) { WaitingForSharedKey.Add(clientIndex); } byte[] b = Encoding.GetEncoding(28591).GetBytes("SharedKey:"); server.SendDataAsync(clientIndex, b, b.Length, (x, y, z) => { }); Debug.Console(1, this, Debug.ErrorLogLevel.Notice, "Sent Shared Key Request to client at {0}", server.GetAddressServerAcceptedConnectionFromForSpecificClient(clientIndex)); } else { OnServerClientReadyForCommunications(clientIndex); } if (HeartbeatRequired) { if (!HeartbeatTimerDictionary.ContainsKey(clientIndex)) { HeartbeatTimerDictionary.Add(clientIndex, new CTimer(HeartbeatTimer_CallbackFunction, clientIndex, HeartbeatRequiredIntervalMs)); } } server.ReceiveDataAsync(clientIndex, SecureReceivedDataAsyncCallback); } } else { Debug.Console(1, this, Debug.ErrorLogLevel.Error, "Client attempt faulty."); } } catch (Exception ex) { Debug.Console(2, this, Debug.ErrorLogLevel.Error, "Error in Socket Status Connect Callback. Error: {0}", ex); } // Rearm the listner SocketErrorCodes status = server.WaitForConnectionAsync(IPAddress.Any, SecureConnectCallback); if (status != SocketErrorCodes.SOCKET_OPERATION_PENDING) { Debug.Console(0, this, Debug.ErrorLogLevel.Error, "Socket status connect callback status {0}", status); if (status == SocketErrorCodes.SOCKET_CONNECTION_IN_PROGRESS) { // There is an issue where on a failed negotiation we need to stop and start the server. This should still leave connected clients intact. server.Stop(); Listen(); } } }
// Show the status of the client index if specified, and always show the current server state public void ShowStatus(string arg) { if (server != null) { if (arg != "") // Optionally, the user may specify a client index to show that client's socket status { uint clientIndex = 0; try { clientIndex = uint.Parse(arg); } catch { CrestronConsole.PrintLine("Could not parse clientIndex"); return; } CrestronConsole.PrintLine("Socket status of client " + clientIndex + ": " + server.GetServerSocketStatusForSpecificClient(clientIndex)); } CrestronConsole.PrintLine("Server state is: " + server.State); // If the SecureTCPServer object exists, always show its state } else { CrestronConsole.PrintLine("No server exists"); } }
/// <summary> /// Secure TCP Client Connected to Secure Server Callback /// </summary> /// <param name="mySecureTCPServer"></param> /// <param name="clientIndex"></param> void SecureConnectCallback(SecureTCPServer server, uint clientIndex) { try { Debug.Console(1, this, Debug.ErrorLogLevel.Notice, "ConnectCallback: IPAddress: {0}. Index: {1}. Status: {2}", server.GetAddressServerAcceptedConnectionFromForSpecificClient(clientIndex), clientIndex, server.GetServerSocketStatusForSpecificClient(clientIndex)); if (clientIndex != 0) { if (server.ClientConnected(clientIndex)) { if (!ConnectedClientsIndexes.Contains(clientIndex)) { ConnectedClientsIndexes.Add(clientIndex); } if (SharedKeyRequired) { if (!WaitingForSharedKey.Contains(clientIndex)) { WaitingForSharedKey.Add(clientIndex); } byte[] b = Encoding.GetEncoding(28591).GetBytes("SharedKey:"); server.SendDataAsync(clientIndex, b, b.Length, (x, y, z) => { }); Debug.Console(1, this, Debug.ErrorLogLevel.Notice, "Sent Shared Key Request to client at {0}", server.GetAddressServerAcceptedConnectionFromForSpecificClient(clientIndex)); } else { OnServerClientReadyForCommunications(clientIndex); } if (HeartbeatRequired) { if (!HeartbeatTimerDictionary.ContainsKey(clientIndex)) { HeartbeatTimerDictionary.Add(clientIndex, new CTimer(HeartbeatTimer_CallbackFunction, clientIndex, HeartbeatRequiredIntervalMs)); } } server.ReceiveDataAsync(clientIndex, SecureReceivedDataAsyncCallback); } } else { Debug.Console(1, this, Debug.ErrorLogLevel.Error, "Client attempt faulty."); if (!ServerStopped) { server.WaitForConnectionAsync(IPAddress.Any, SecureConnectCallback); return; } } } catch (Exception ex) { Debug.Console(2, this, Debug.ErrorLogLevel.Error, "Error in Socket Status Connect Callback. Error: {0}", ex); } //Debug.Console(1, this, Debug.ErrorLogLevel, "((((((Server State bitfield={0}; maxclient={1}; ServerStopped={2}))))))", // server.State, // MaxClients, // ServerStopped); if ((server.State & ServerState.SERVER_LISTENING) != ServerState.SERVER_LISTENING && MaxClients > 1 && !ServerStopped) { Debug.Console(1, this, Debug.ErrorLogLevel.Notice, "Waiting for next connection"); server.WaitForConnectionAsync(IPAddress.Any, SecureConnectCallback); } }