public ServerListener(string certificatePath, string ipv4, int port) { this.tcpListener = new TcpListener(new IPEndPoint(IPAddress.Parse(ipv4), port)); this.packetHandler = new PacketHandler(); this.iODataHandler = new IODataHandler(); this.connectedClients = new List <TcpClient>(); this.clientThreads = new Dictionary <TcpClient, Thread>(); this.clientForClientId = new Dictionary <string, TcpClient>(); this.doctorForClient = new Dictionary <TcpClient, TcpClient>(); this.clientStreams = new Dictionary <TcpClient, SslStream>(); this.serverCertificate = new X509Certificate2(certificatePath, "banaantje"); }
public async void WaitForClients() { TcpClient clientConnected = null; try { clientConnected = await tcpListener.AcceptTcpClientAsync(); connectedClients.Add(clientConnected); Console.WriteLine($"\t> Client {clientConnected.Client.RemoteEndPoint.ToString()} connected"); Console.WriteLine(); SetupSslStreamForClient(clientConnected); Console.WriteLine(); Thread clientThread = new Thread(async() => { bool running = true; while (running) { TcpClient clientInThread = null; try { clientInThread = clientConnected; byte[] packetLengthBytes = ReadFromStream(clientInThread, 4); if (packetLengthBytes.Length == 4) { int packetLength = BitConverter.ToInt32(packetLengthBytes, 0); byte[] packetData = ReadFromStream(clientInThread, packetLength); string responsepacket = Encoding.UTF8.GetString(packetData); Tuple <string[], PacketType> packetBundle = packetHandler.HandlePacket(responsepacket); switch (packetBundle.Item2) { case PacketType.ClientLogin: Console.WriteLine($"\t> Client LogIn packet received from {clientInThread.Client.RemoteEndPoint.ToString()}"); //IODataHandler.SaveTestEncryptedData(); //Client/Login\r\n123\r\nname if (packetBundle.Item1.Length == 2) { string clientId = packetBundle.Item1[0]; string name = packetBundle.Item1[1]; if (!clientForClientId.ContainsKey(clientId) && !clientForClientId.ContainsValue(clientInThread)) { int id; if (int.TryParse(clientId, out id)) { ClientCollection clientCollection = IODataHandler.LoadClients(); if (clientCollection.clients.Any(x => x.Id == id && x.Name == name)) { clientForClientId.Add(clientId, clientInThread); SendWithNoResponse(clientInThread, "Server/Status\r\nok"); } else { SendWithNoResponse(clientInThread, "Server/Status\r\nnotok"); } } else { SendWithNoResponse(clientInThread, "Server/Status\r\nnotok"); } } else { SendWithNoResponse(clientInThread, "Server/Status\r\nnotok"); } } break; case PacketType.ClientLogout: Console.WriteLine($"\t> Client LogOut packet received from {clientInThread.Client.RemoteEndPoint.ToString()}"); if (doctorForClient.ContainsKey(clientInThread)) { TcpClient doctorFromClient = doctorForClient[clientInThread]; Console.WriteLine($"\t\t> Send client disconnect to {doctorFromClient.Client.RemoteEndPoint.ToString()}"); SendWithNoResponse(doctorFromClient, $"Server/ClientDisconnect\r\n"); doctorForClient.Remove(clientInThread); } if (clientForClientId.ContainsValue(clientInThread)) { clientForClientId.Remove(clientForClientId.First(x => x.Value == clientInThread).Key); } if (connectedClients.Contains(clientInThread)) { connectedClients.Remove(clientInThread); } clientInThread.Close(); Console.WriteLine($"\t\t> Client {clientInThread.Client.RemoteEndPoint.ToString()} disconnected"); running = false; break; case PacketType.ClientVr: Console.WriteLine($"\t> Client VR packet received from {clientInThread.Client.RemoteEndPoint.ToString()}"); // Obsolete until further notice break; case PacketType.ClientSyncData: Console.WriteLine($"\t> Client SyncData packet received from {clientInThread.Client.RemoteEndPoint.ToString()}"); // Client/SyncData\r\nBIKE\r\nHEART string[] syncData = packetBundle.Item1; if (syncData.Length == 3) { if (clientForClientId.ContainsKey(syncData[0])) { TcpClient clientForId = clientForClientId[syncData[0]]; if (doctorForClient.ContainsKey(clientForId)) { TcpClient connectedDoctor = doctorForClient[clientForId]; SendWithNoResponse(connectedDoctor, $"Server/SyncData\r\n{syncData[1]}\r\n{syncData[2]}"); Console.WriteLine($"\t\t> Send client sync data to {connectedDoctor.Client.RemoteEndPoint.ToString()}"); } } } break; case PacketType.ClientHeart: Console.WriteLine($"\t> Client Heart packet received from {clientInThread.Client.RemoteEndPoint.ToString()}"); string[] heartData = packetBundle.Item1; if (heartData.Length == 2) { if (clientForClientId.ContainsKey(heartData[0])) { TcpClient clientForId = clientForClientId[heartData[0]]; if (doctorForClient.ContainsKey(clientForId)) { TcpClient connectedDoctor = doctorForClient[clientForId]; SendWithNoResponse(connectedDoctor, $"Server/Heart\r\n{heartData[1]}"); } } } break; case PacketType.ClientClose: Console.WriteLine($"\t> Client Close packet received from {clientInThread.Client.RemoteEndPoint.ToString()}"); if (packetBundle.Item1.Length == 1) { if (doctorForClient.ContainsKey(clientInThread)) { TcpClient doctorFromClient = doctorForClient[clientInThread]; doctorForClient.Remove(clientInThread); Console.WriteLine($"\t\t> Closed tunnel between {doctorFromClient.Client.RemoteEndPoint.ToString()} and {clientInThread.Client.RemoteEndPoint.ToString()}"); SendWithNoResponse(doctorFromClient, $"Server/ClientDisconnect\r\n"); Console.WriteLine($"\t\t> Send close to {doctorFromClient.Client.RemoteEndPoint.ToString()}"); } } break; case PacketType.ClientMessage: Console.WriteLine($"\t> Client Message packet received from {clientInThread.Client.RemoteEndPoint.ToString()}"); if (packetBundle.Item1.Length == 1) { if (doctorForClient.ContainsKey(clientInThread)) { string clientMessage = packetBundle.Item1[0]; TcpClient doctorFromClient = doctorForClient[clientInThread]; SendWithNoResponse(doctorFromClient, $"Server/Message\r\n{clientMessage}"); Console.WriteLine($"\t\t> Send message to {doctorFromClient.Client.RemoteEndPoint.ToString()}"); } } break; case PacketType.DoctorLogin: Console.WriteLine($"\t> Doctor Login packet received from {clientInThread.Client.RemoteEndPoint.ToString()}"); string[] loginData = packetBundle.Item1; if (loginData.Length == 2) { Doctor doctor = await iODataHandler.GetDoctorAsync(loginData[0], loginData[1]); if (doctor != null) { SendWithNoResponse(clientInThread, "Server/Status\r\nok"); } else { SendWithNoResponse(clientInThread, "Server/Status\r\nnotok"); } } break; case PacketType.DoctorLogout: Console.WriteLine($"\t> Doctor LogOut packet received from {clientInThread.Client.RemoteEndPoint.ToString()}"); if (doctorForClient.Values.Contains(clientInThread)) { TcpClient targetPatientClient = doctorForClient[doctorForClient.First(x => x.Value == clientInThread).Key]; Console.WriteLine($"\t\t> Send doctor disconnect to {targetPatientClient.Client.RemoteEndPoint.ToString()}"); SendWithNoResponse(targetPatientClient, $"Server/DoctorDisconnect\r\n"); doctorForClient.Remove(targetPatientClient); } connectedClients.Remove(clientInThread); clientInThread.Close(); Console.WriteLine($"\t\t> Client {clientInThread.Client.RemoteEndPoint.ToString()} disconnected"); running = false; break; case PacketType.DoctorResistance: Console.WriteLine($"\t> Doctor Resistance packet received from {clientInThread.Client.RemoteEndPoint.ToString()}"); //Doctor/Resistance\r\nRESISTANCE if (packetBundle.Item1.Length == 1) { if (doctorForClient.Values.Contains(clientInThread)) { string resistance = packetBundle.Item1[0]; TcpClient targetPatientClient = doctorForClient.First(x => x.Value == clientInThread).Key; SendWithNoResponse(targetPatientClient, $"Server/Resistance\r\n{resistance}"); } } break; case PacketType.DoctorDataGet: Console.WriteLine($"\t> Doctor DataGet packet received from {clientInThread.Client.RemoteEndPoint.ToString()}"); if (packetBundle.Item1[0] == "ALL_CLIENTS") { ClientCollection clientCollection = IODataHandler.LoadClients(); string packet = "Server/DataGet\r\n"; for (int i = 0; i < clientCollection.clients.Count; i++) { packet += clientCollection.clients[i].Name + "//" + clientCollection.clients[i].Id + "//" + clientCollection.clients[i].Birthdate + "//" + clientCollection.clients[i].Gender + "//"; } SendWithNoResponse(clientInThread, packet); } else { SendWithNoResponse(clientInThread, "Server/Status\r\nnotok"); } break; case PacketType.DoctorDataSave: Console.WriteLine($"\t> Doctor DataSave packet received from {clientInThread.Client.RemoteEndPoint.ToString()}"); // Obsolete until further notice break; case PacketType.DoctorAddNewClient: Console.WriteLine($"\t> Doctor AddNewClient packet received from {clientInThread.Client.RemoteEndPoint.ToString()}"); // EG: Doctor/AddNewClient\r\nNAME string[] newClientData = packetBundle.Item1; if (newClientData.Length == 1) { int newId = await iODataHandler.ProvideNewClientId(); if (newId > -1) { Client newClient = new Client(); newClient.Name = newClientData[0]; newClient.Id = newId; bool saved = await iODataHandler.AddClientAsync(newClient); if (saved) { SendWithNoResponse(clientInThread, "Server/Status\r\nok"); } else { SendWithNoResponse(clientInThread, "Server/Status\r\nnotok"); } } else { SendWithNoResponse(clientInThread, "Server/Status\r\nnotok"); } } break; case PacketType.DoctorAddClientHistory: Console.WriteLine($"\t> Doctor AddClientHistory packet received from {clientInThread.Client.RemoteEndPoint.ToString()}"); // EG: Doctor/AddClientHistory\r\nCLIENT_ID\r\nDATETIME\r\nHEARTRATE_BIKE_JSON_DATA string[] saveData = packetBundle.Item1; if (saveData.Length == 3) { int idParseResult = 0; if (int.TryParse(saveData[0], out idParseResult)) { Client client = await iODataHandler.GetClientAsync(idParseResult); if (client != null) { ClientData newClientDataEntry = new ClientData(); newClientDataEntry.clientId = client.Id; DateTime dateParseResult; if (DateTime.TryParse(saveData[1], out dateParseResult)) { newClientDataEntry.Date = dateParseResult; HistoryItem historyItem = JsonConvert.DeserializeObject <HistoryItem>(saveData[2]); newClientDataEntry.bikeData = historyItem.BikeData; newClientDataEntry.heartRateData = historyItem.HeartData; bool saved = await iODataHandler.AddClientDataAsync(newClientDataEntry); Thread.Sleep(200); if (saved) { SendWithNoResponse(clientInThread, "Server/Status\r\nok"); } else { SendWithNoResponse(clientInThread, "Server/Status\r\nnotok"); } } else { SendWithNoResponse(clientInThread, "Server/Status\r\nnotok"); } } else { SendWithNoResponse(clientInThread, "Server/Status\r\nnotok"); } } else { SendWithNoResponse(clientInThread, "Server/Status\r\nnotok"); } } else { SendWithNoResponse(clientInThread, "Server/Status\r\nnotok"); } break; case PacketType.DoctorGetClientHistory: Console.WriteLine($"\t> Doctor AddClientHistory packet received from {clientInThread.Client.RemoteEndPoint.ToString()}"); // EG: Doctor/GetClientHistory\r\nCLIENT_ID\r\nDATE string[] getData = packetBundle.Item1; if (getData.Length == 2) { int idParseResult = 0; if (int.TryParse(getData[0], out idParseResult)) { DateTime dateParseResult; if (DateTime.TryParse(getData[1], out dateParseResult)) { // Filter based on year, month and day ClientData clientData = await iODataHandler.GetClientDataAsync(idParseResult, dateParseResult); string json = JsonConvert.SerializeObject(clientData); string packet = $"Server/GetClientHistory\r\n{clientData.Date.ToString()}\r\n{json}"; SendWithNoResponse(clientInThread, packet); } } else { SendWithNoResponse(clientInThread, "Server/Status\r\nnotok"); } } else { SendWithNoResponse(clientInThread, "Server/Status\r\nnotok"); } break; case PacketType.DoctorBroadcast: Console.WriteLine($"\t> Doctor Broadcast packet received from {clientInThread.Client.RemoteEndPoint.ToString()}"); if (packetBundle.Item1.Length == 1) { TcpClient[] clColl = doctorForClient.Keys.ToArray(); for (int i = 0; i < clColl.Length; i++) { SendWithNoResponse(clColl[i], $"Server/Broadcast\r\n{packetBundle.Item1[0]}"); Thread.Sleep(100); } TcpClient[] dcColl = doctorForClient.Values.ToArray(); for (int i = 0; i < dcColl.Length; i++) { SendWithNoResponse(dcColl[i], $"Server/Broadcast\r\n{packetBundle.Item1[0]}"); Thread.Sleep(100); } } break; case PacketType.DoctorClose: Console.WriteLine($"\t> Doctor Close packet received from {clientInThread.Client.RemoteEndPoint.ToString()}"); if (packetBundle.Item1.Length == 1) { if (doctorForClient.Values.Contains(clientInThread)) { TcpClient targetPatientClient = doctorForClient.First(x => x.Value == clientInThread).Key; if (doctorForClient.ContainsKey(targetPatientClient)) { doctorForClient.Remove(targetPatientClient); Console.WriteLine($"\t\t> Closed tunnel between {clientInThread.Client.RemoteEndPoint.ToString()} and {targetPatientClient.Client.RemoteEndPoint.ToString()}"); SendWithNoResponse(targetPatientClient, $"Server/DoctorDisconnect\r\n"); Console.WriteLine($"\t\t> Send close to {targetPatientClient.Client.RemoteEndPoint.ToString()}"); } } } break; case PacketType.DoctorStopVR: Console.WriteLine($"\t> Doctor Stop VR packet received from {clientInThread.Client.RemoteEndPoint.ToString()}"); //Doctor/StopVR if (packetBundle.Item1.Length == 1) { if (doctorForClient.Values.Contains(clientInThread)) { TcpClient targetPatientClient = doctorForClient.First(x => x.Value == clientInThread).Key; SendWithNoResponse(targetPatientClient, $"Server/StopVR\r\n"); Console.WriteLine($"\t\t> Send stop VR to {targetPatientClient.Client.RemoteEndPoint.ToString()}"); } } break; case PacketType.DoctorMessage: Console.WriteLine($"\t> Doctor Message packet received from {clientInThread.Client.RemoteEndPoint.ToString()}"); //Doctor/Message\r\ntext if (packetBundle.Item1.Length == 1) { string doctorMessage = packetBundle.Item1[0]; if (doctorForClient.Values.Contains(clientInThread)) { TcpClient targetPatientClient = doctorForClient.First(x => x.Value == clientInThread).Key; SendWithNoResponse(targetPatientClient, $"Server/Message\r\n{doctorMessage}"); Console.WriteLine($"\t\t> Send message to {targetPatientClient.Client.RemoteEndPoint.ToString()}"); } } break; case PacketType.DoctorConnectToClient: Console.WriteLine($"\t> Doctor ConnectToClient packet received from {clientInThread.Client.RemoteEndPoint.ToString()}"); //Doctor/ConnectToClient\r\n123 if (packetBundle.Item1.Length == 1) { if (clientForClientId.ContainsKey(packetBundle.Item1[0])) { TcpClient selectedPatientClient = clientForClientId[packetBundle.Item1[0]]; if (!doctorForClient.ContainsKey(selectedPatientClient)) { doctorForClient.Add(selectedPatientClient, clientInThread); Console.WriteLine($"\t\t> Tunnel created between {clientInThread.Client.RemoteEndPoint.ToString()} and {selectedPatientClient.Client.RemoteEndPoint.ToString()}"); SendWithNoResponse(clientInThread, "Server/Status\r\nok"); SendWithNoResponse(selectedPatientClient, "Server/Status\r\nready"); } else { SendWithNoResponse(clientInThread, "Server/Status\r\nnotok"); } } else { SendWithNoResponse(clientInThread, "Server/Status\r\nnotok"); } } break; case PacketType.UnknownPacket: Console.WriteLine($"\t> Unknown packet received from {clientInThread.Client.RemoteEndPoint.ToString()}"); break; case PacketType.EmptyPacket: Console.WriteLine($"\t> Empty packet received from {clientInThread.Client.RemoteEndPoint.ToString()}"); break; default: break; } Console.WriteLine("\t\t> Handled packet"); } else { running = false; } } catch (Exception ex) { try { Console.WriteLine($"\t> Error ocurred from connecting client: {clientConnected.Client.RemoteEndPoint.ToString()}\n" + ex.InnerException + "\n" + ex.Message + "\n" + ex.StackTrace); if (clientInThread != null) { clientStreams.Remove(clientInThread); } running = false; } catch (ObjectDisposedException) { // client cleared } } } }); // Threads per client bijhouden voor latere cleanup clientThreads.Add(clientConnected, clientThread); clientThread.Start(); WaitForClients(); } catch (Exception ex) { Console.WriteLine($"Error ocurred during client wait!\n" + ex.InnerException + ex.Message + "\n" + ex.StackTrace); if (clientConnected != null) { clientStreams.Remove(clientConnected); } } }