using System.Collections.Generic; using System.Diagnostics; using Newtonsoft.Json.Linq; using System.Net; using PolyChat.Models; using SocketIOSharp.Server; using SocketIOSharp.Server.Client; using System.IO; using System.Threading; using System; using System.Text; using System.Security.Cryptography; namespace PolyChat { // 10.1.211.26 Marc // 10.1.218.90 Felix // 10.4.141.77 Pat class Controller { // Constants private const ushort PORT = 8050; // Controller private readonly MainPage UIController; // Props private Dictionary Connections = new Dictionary(); private string OwnName = ""; private string OwnIP; /// /// Initializes Controller with UI access /// /// UWP UI Controller public Controller(MainPage uiController) { UIController = uiController; OwnIP = getIP(); Serve(); // test UIController.OnIncomingConnection("1.1.1.1"); UIController.OnIncomingConnection("1.2.3.4"); UIController.OnIncomingConnection("1.2.4.8"); } public void Connect(string ip) { Debug.WriteLine("--- Controller.Connect ---"); if (isInConnections(ip)) { Debug.WriteLine("---- We have an active connection to this client. ABORT! ----"); CloseChatUI(ip); //Todo show error! } else { Connections.Add(ip, new Connection(ip, PORT, Data => OnMessage(ip, Data), CloseChat)); } } private void Serve() { Debug.WriteLine("--- Controller.Serve ---"); SocketIOServer server = new SocketIOServer(new SocketIOServerOption(PORT)); server.Start(); Debug.WriteLine("Port " + server.Option.Port); Debug.WriteLine("Path " + server.Option.Path); // listen for connection server.OnConnection((SocketIOSocket socket) => { Debug.WriteLine("--- Client connected! ---"); // setup event listeners socket.On("initial", (JToken[] data) => { Debug.WriteLine("--- initial packet received ---"); string ForeignIp = data[0].ToString(); Debug.WriteLine($"--- this ip was in the inital packet: {ForeignIp} ---"); if (isInConnections(ForeignIp)) { Debug.WriteLine("---- We have an active connection to this client. ABORT! ----");//Todo show error! CloseChatUI(ForeignIp); } else { Connections.Add(ForeignIp, new Connection(socket, Data => OnMessage(ForeignIp, Data), CloseChat)); UIController.OnIncomingConnection(ForeignIp); } }); }); } public void SendBroadcastMessage(string type, string content) { Debug.WriteLine("--- Controller.Broadcast ---"); foreach (KeyValuePair entry in Connections) { SendMessage(entry.Key, type, content); } } public void SendMessage(string ip, string type, string content) { Debug.WriteLine("--- Controller.SendMessage ---"); Debug.WriteLine($"{type} -> {ip} content: {content}"); JObject json = new JObject( new JProperty("type", type), new JProperty("content", content) ); Debug.WriteLine($"json: {json.ToString()}"); // send as json Connections[ip].SendMessage(json.ToString()); // save to logs SaveChats(ip, json.ToString(), DateTime.Now); } private void OnMessage(string ip, JToken[] data) { Debug.WriteLine("--- Controller.OnMessage ---"); if (data != null && data.Length > 0 && data[0] != null) { DateTime now = DateTime.Now; Debug.WriteLine("RAW: " + data[0]); UIController.OnIncomingMessage(ip, data[0].ToString(), now); SaveChats(ip, data[0].ToString(), now); } else Debug.WriteLine("Undefined: " + data); } public void CloseChat(string IP, bool wasConnected = true) { Debug.WriteLine($"Deleting connection with IP:{IP}"); if (IP != null && Connections.ContainsKey(IP)) { Connections[IP].Close(); Connections.Remove(IP); } CloseChatUI(IP, wasConnected); } private void CloseChatUI(string IP, bool wasConnected = true) { UIController.OnChatPartnerDeleted(IP); string heading = wasConnected ? "Connection Closed" : "Connection Failed"; if (!wasConnected) UIController.ShowConnectionError(IP, heading, $"Connecting to {IP} failed..."); } private bool isInConnections(string IP) { return Connections.ContainsKey(IP); } public bool IsConnected(string ip) { return Connections.ContainsKey(ip) && Connections[ip].IsConnected(); } public static string getIP() { IPHostEntry ipEntry = Dns.GetHostEntry(Dns.GetHostName()); IPAddress[] addrList = ipEntry.AddressList; for (short i = 0; i < addrList.Length; i++) { if (addrList[i].ToString().Substring(0, 3).Equals("10.")) { return addrList[i].ToString(); } } return null; } /// /// sends chatlogs as json array to uiController wit corrosponding ip /// /// public void loadChats() { //TODO: also load chatlogs when user tries to connect //load dir and create if non existant if (Directory.Exists("U:\\PolyChat\\Saves")) { Debug.WriteLine("--Path exists.--"); } else { Directory.CreateDirectory("U:\\PolyChat\\Saves"); Debug.WriteLine("--Path Created--."); } //go through all files and send ip and json array to ui String[] filepaths = Directory.GetFiles("U:\\PolyChat\\Saves"); if (filepaths.Length > 0) { Debug.WriteLine("---Loading Saves"); foreach (String path in filepaths) { Debug.WriteLine($"--{path}"); String jsonArr = File.ReadAllText(path); String ip = Path.GetFileName(path); ip = ip.Substring(0, ip.Length - 4); Debug.WriteLine($"-{ip}"); Debug.WriteLine(jsonArr); UIController.OnIncomingConnection(ip); UIController.OnIncomingMessages(ip, jsonArr); } } } /* public void loadChat(String ip) { //TODO: also load chatlogs when user tries to connect //load dir and create if non existant if (Directory.Exists("U:\\PolyChat\\Saves")) { Debug.WriteLine("--Path exists.--"); } else { Directory.CreateDirectory("U:\\PolyChat\\Saves"); Debug.WriteLine("--Path Created--."); } //go through all files and send ip and json array to ui String[] filepaths = Directory.GetFiles("U:\\PolyChat\\Saves"); if (filepaths.Length > 0) { Debug.WriteLine("---Loading Saves"); foreach (String path in filepaths) { Debug.WriteLine($"--{path}"); String jsonArr = File.ReadAllText(path); String ip = Path.GetFileName(path); ip = ip.Substring(0, ip.Length - 4); Debug.WriteLine($"-{ip}"); Debug.WriteLine(jsonArr); Connect(ip); UIController.OnIncomingConnection(ip); UIController.OnIncomingMessages(ip, jsonArr); } } } */ /// /// Saves incoming chat message to /// /// /// public void SaveChats(string ip, string json, DateTime timeStamp) { //Vielleicht noch so machen dass die mit gleicher ip nacheinander gemacht //werden damit es nicht zu überschreibungen kommt vielleicth auch ganz oben oder am ende ne //writing flag setzen oder auch in der datei selbst ne flag setzen new Thread(() => { //breaking if namechange JObject obj = JObject.Parse(json); if (!obj["type"].ToString().Equals("username")) { //adding timestamp obj = JObject.Parse(json); obj.Add(new JProperty("timestamp", timeStamp)); json = obj.ToString(); if (File.Exists($"U:\\PolyChat\\Saves\\{ip}.txt")) { Debug.WriteLine("--File allready exists--"); //check for integraty of file string output = File.ReadAllText($"U:\\PolyChat\\Saves\\{ip}.txt"); Debug.WriteLine($"---{output}---"); if (output.Substring(0, 1).Equals("[") && output.Substring(output.Length - 1, 1).Equals("]")) { Debug.WriteLine("--adding new chatmessage--"); //structure intact //save new chat String saved = output.Substring(0, output.Length - 1); output = saved + ", " + json + " ]"; File.Delete($"U:\\PolyChat\\Saves\\{ip}.txt"); File.WriteAllText($"U:\\PolyChat\\Saves\\{ip}.txt", output); } else { Debug.WriteLine("--Structure not intact--"); Debug.WriteLine("--redoing file--"); //structure not intact //redo file File.Delete($"U:\\PolyChat\\Saves\\{ip}.txt"); File.WriteAllText($"U:\\PolyChat\\Saves\\{ip}.txt", $"[ {json} ]"); } } else { Debug.WriteLine("--Creating new File--"); //setup file File.WriteAllText($"U:\\PolyChat\\Saves\\{ip}.txt", $"[ {json} ]"); } } }).Start(); } private void encode(string json) { byte[] plaintext = Encoding.UTF8.GetBytes(json); byte[] entropy = new byte[20]; using (RNGCryptoServiceProvider rng = new RNGCryptoServiceProvider()) { rng.GetBytes(entropy); } } } }