private void ConnectionDataCallback(SecureTCPServer server, uint clientIndex, int numberOfBytesReceived) { try { byte[] data = server.GetIncomingDataBufferForSpecificClient(clientIndex); string dataASCIIEncoded = Encoding.ASCII.GetString(data, 0, data.Length); //TODO: Cambiare la regex e renderla sicura if (new Regex("^GET").IsMatch(dataASCIIEncoded)) { CrestronLogger.WriteToLog("WS_SERVER - PERFORMING HANDSHAKE", 1); PerformHandShake(clientIndex, dataASCIIEncoded); if (server.ClientConnected(clientIndex)) { oldDecodedFrame.Add(clientIndex, new List <byte>()); server.ReceiveDataAsync(clientIndex, ReceiveCallback); } } else { RejectConnection(clientIndex); } } catch (Exception) { CrestronLogger.WriteToLog("WS_SERVER - ConnectionCallback - connection error ", 8); RejectConnection(clientIndex); } }
public void Disconnect(string args) { try { if (server == null) { CrestronConsole.PrintLine("Server is already disconnected"); return; } if (args == "") { // When no arguments are provided, disconnect from all clients and destroy the server server.DisconnectAll(); CrestronConsole.PrintLine("Server has disconnected from all clients and is no longer listening on port " + server.PortNumber); server = null; } else { // Disconnect from the client specified by the user uint clientIndex = uint.Parse(args); if (server.ClientConnected(clientIndex)) { server.Disconnect(clientIndex); CrestronConsole.PrintLine("Server has disconnected from " + clientIndex); } else { CrestronConsole.PrintLine("Client #" + clientIndex + " does not exist currently"); } } } catch (Exception e) { PrintAndLog("Error in Disconnect: " + e.Message); } }
/// <summary> /// Secure TCP Client Connected to Secure Server Callback /// </summary> /// <param name="mySecureTCPServer"></param> /// <param name="clientIndex"></param> void SecureConnectCallback(SecureTCPServer mySecureTCPServer, uint clientIndex) { if (mySecureTCPServer.ClientConnected(clientIndex)) { if (SharedKeyRequired) { 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)); } if (HeartbeatRequired) { CTimer HeartbeatTimer = new CTimer(HeartbeatTimer_CallbackFunction, clientIndex, HeartbeatRequiredIntervalMs); HeartbeatTimerDictionary.Add(clientIndex, HeartbeatTimer); } mySecureTCPServer.ReceiveDataAsync(clientIndex, SecureReceivedDataAsyncCallback); if (mySecureTCPServer.State != ServerState.SERVER_LISTENING && MaxClients > 1 && !ServerStopped) { mySecureTCPServer.WaitForConnectionAsync(IPAddress.Any, SecureConnectCallback); } } }
/// <summary> /// Disconnect All Clients /// </summary> public void DisconnectAllClientsForShutdown() { Debug.Console(1, this, Debug.ErrorLogLevel.Notice, "Disconnecting All Clients"); if (SecureServer != null) { SecureServer.SocketStatusChange -= SecureServer_SocketStatusChange; foreach (var index in ConnectedClientsIndexes.ToList()) // copy it here so that it iterates properly { var i = index; if (!SecureServer.ClientConnected(index)) { continue; } try { SecureServer.Disconnect(i); Debug.Console(2, this, Debug.ErrorLogLevel.Notice, "Disconnected client index: {0}", i); } catch (Exception ex) { Debug.Console(2, this, Debug.ErrorLogLevel.Error, "Error Disconnecting client index: {0}. Error: {1}", i, ex); } } Debug.Console(2, this, Debug.ErrorLogLevel.Notice, "Server Status: {0}", SecureServer.ServerSocketStatus); } Debug.Console(2, this, Debug.ErrorLogLevel.Notice, "Disconnected All Clients"); ConnectedClientsIndexes.Clear(); if (!ProgramIsStopping) { OnConnectionChange(); OnServerStateChange(SecureServer.State); //State shows both listening and connected } // var o = new { }; }
/// <summary> /// The callback for receiving data from the secure server client. /// </summary> /// <param name="server">The server the callback is executed on.</param> /// <param name="clientIndex">The index of the client data is received from.</param> /// <param name="count">The number of bytes of data received.</param> private void SecureReceiveDataCallback(SecureTCPServer server, uint clientIndex, int count) { if (count <= 0) { if (server.ClientConnected(clientIndex)) { server.ReceiveDataAsync(clientIndex, SecureReceiveDataCallback); } return; } var dataBuffer = server.GetIncomingDataBufferForSpecificClient(clientIndex); var data = Encoding.UTF8.GetString(dataBuffer, 0, count); if (Regex.IsMatch(data, "^GET", RegexOptions.IgnoreCase)) { var key = Regex.Match(data, "Sec-WebSocket-Key: (.*)").Groups[1].Value.Trim(); key = key + "258EAFA5-E914-47DA-95CA-C5AB0DC85B11"; byte[] keySha1 = Crestron.SimplSharp.Cryptography.SHA1.Create().ComputeHash(Encoding.UTF8.GetBytes(key)); string sha64 = Convert.ToBase64String(keySha1); var responseMessage = "HTTP/1.1 101 Switching Protocols\r\n" + "Connection: Upgrade\r\n" + "Upgrade: websocket\r\n" + "Sec-WebSocket-Accept: " + sha64 + "\r\n\r\n"; this.Send(responseMessage, clientIndex, false); } else { CrestronConsole.PrintLine("Received '{0}' bytes.", count); bool fin = (dataBuffer[0] & 128) != 0; bool mask = (dataBuffer[1] & 128) != 0; int opcode = dataBuffer[0] & 15; ulong dataLength = (ulong)(dataBuffer[1] - 128); ulong offset = 2; if (opcode == 0x0) { CrestronConsole.PrintLine("Received continuation frame opcode."); } else if (opcode == 0x1) { CrestronConsole.PrintLine("Received text frame opcode."); } else if (opcode == 0x2) { CrestronConsole.PrintLine("Received binary frame opcode."); } else if (opcode >= 0x3 && opcode <= 0x7) { CrestronConsole.PrintLine("Received reserved non-control opcode."); } else if (opcode == 0x8) { this.Send(new byte[] { BitConverter.GetBytes(0x88)[0], BitConverter.GetBytes(0x00)[0] }, clientIndex, false); server.Disconnect(clientIndex); CrestronConsole.PrintLine("Received disconnect OpCode. Disconnected."); return; } else if (opcode == 0x9) { this.Send(new byte[] { BitConverter.GetBytes(0x8A)[0], BitConverter.GetBytes(0x00)[0] }, clientIndex, false); CrestronConsole.PrintLine("Received Ping and sent a Pong."); if (server.ClientConnected(clientIndex)) { server.ReceiveDataAsync(clientIndex, SecureReceiveDataCallback); } return; } else if (opcode == 0xA) { CrestronConsole.PrintLine("Received Pong."); if (server.ClientConnected(clientIndex)) { server.ReceiveDataAsync(clientIndex, SecureReceiveDataCallback); } return; } else if (opcode >= 0xB && opcode <= 0xF) { CrestronConsole.PrintLine("Received reserved control frame opcode."); } if (dataLength == 126) { CrestronConsole.PrintLine("Data length is 126."); dataLength = BitConverter.ToUInt16(new byte[] { dataBuffer[3], dataBuffer[2] }, 0); offset = 4; } else if (dataLength == 127) { CrestronConsole.PrintLine("Data length is 127."); dataLength = BitConverter.ToUInt64(new byte[] { dataBuffer[9], dataBuffer[8], dataBuffer[7], dataBuffer[6], dataBuffer[5], dataBuffer[4], dataBuffer[3], dataBuffer[2] }, 0); offset = 10; } if (dataLength == 0) { CrestronConsole.PrintLine("Data length was zero."); this.Send(string.Format("{0}>", InitialParametersClass.ControllerPromptName), clientIndex, true); } else if (mask) { byte[] de = new byte[dataLength]; byte[] mk = new byte[4] { dataBuffer[offset], dataBuffer[offset + 1], dataBuffer[offset + 2], dataBuffer[offset + 3] }; offset += 4; for (ulong i = 0; i < dataLength; i++) { de[i] = (byte)(dataBuffer[offset + i] ^ mk[i % 4]); } var text = Encoding.UTF8.GetString(de, 0, de.Length); var dr = DataReceived; if (dr != null) { dr.Invoke(text, clientIndex); } } else { CrestronConsole.PrintLine("Data length was '{0}', but mask bit not set. Invalid message received.", dataLength); var dbg = string.Empty; for (var i = 0; i < count; i++) { dbg += string.Format("[{0}]", Convert.ToString(dataBuffer[i], 16)); } Debug.WriteDebugLine(this, dbg); } } if (server.ClientConnected(clientIndex)) { server.ReceiveDataAsync(clientIndex, SecureReceiveDataCallback); } }
/// <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(); } } }
/// <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); } }