using System; using System.Diagnostics; using System.Net; using System.Net.Sockets; using System.Text; using System.Threading; namespace MelonVPNCore { public static class DaemonSocketServer { private static Process currentVpnProcess = null; private static bool shouldBeRunning = false; private static bool shouldRestart = true; private static int startingTime = 3000; private static int restartDelay = 250; public static void StartServer() { IPHostEntry host = Dns.GetHostEntry("localhost"); IPAddress ipAddress = host.AddressList[0]; IPEndPoint localEndPoint = new IPEndPoint(ipAddress, 22035); try { Socket listener = new Socket(ipAddress.AddressFamily, SocketType.Stream, ProtocolType.Tcp); listener.Bind(localEndPoint); listener.Listen(10); string lastClientUpdate = Messages.EOF; while (true) { Socket handler = listener.Accept(); string data = null; byte[] bytes = null; while (true) { bytes = new byte[1024]; int bytesRec = handler.Receive(bytes); data += Encoding.ASCII.GetString(bytes, 0, bytesRec); if (data.IndexOf(Messages.EOF, StringComparison.CurrentCulture) > -1) break; } if (data.StartsWith(Messages.ClientListStartMsg, StringComparison.CurrentCulture)) { lastClientUpdate = data; Client.SendCustomMessage(lastClientUpdate, true); } else if (data == Messages.RestartOnMsg) { shouldRestart = true; Client.SendDataMessage(DataMessage.RestartOn, true); } else if (data == Messages.RestartOffMsg) { shouldRestart = false; Client.SendDataMessage(DataMessage.RestartOff, true); } else if (data == Messages.StatusMsg) { Console.WriteLine("Status requested"); if (isProcessOnline(currentVpnProcess) || shouldBeRunning) { Console.WriteLine("Sending response: online"); Client.SendDataMessage(DataMessage.Online, true); Client.SendCustomMessage(lastClientUpdate, true); } else { Console.WriteLine("Sending response: offline"); Client.SendDataMessage(DataMessage.Offline, true); Client.SendCustomMessage(Messages.ClientListEmptyMsg, true); } Client.SendDataMessage((shouldRestart) ? DataMessage.RestartOn : DataMessage.RestartOff); } else if (data == Messages.StartMsg) { if (! isProcessOnline(currentVpnProcess)) { shouldBeRunning = true; Console.WriteLine("Starting VPN"); try { Console.WriteLine("Starting embedded process"); Console.WriteLine("Sending starting reply"); Client.SendDataMessage(DataMessage.Starting, true); if (StartEProcess(true)) { Console.WriteLine("Sending online reply"); Client.SendDataMessage(DataMessage.Online, true); } } catch (Exception e) { shouldBeRunning = false; Console.WriteLine("There was an error. But I fixed it."); Console.WriteLine("It looked like this: " + e); currentVpnProcess.Dispose(); currentVpnProcess = null; Client.SendDataMessage(DataMessage.Error, true); Client.SendCustomMessage(Messages.ClientListEmptyMsg, true); } } else { Console.WriteLine("VPN already started"); } } else if (data == Messages.StopMsg) { shouldBeRunning = false; bool haderr = false; if (isProcessOnline(currentVpnProcess)) { Console.WriteLine("Stopping VPN"); try { currentVpnProcess.EnableRaisingEvents = false; Console.WriteLine("Stopping embedded process"); currentVpnProcess.Kill(); currentVpnProcess = null; } catch (Exception e) { Console.WriteLine("There was an error. But I fixed it."); Console.WriteLine("It looked like this: " + e); currentVpnProcess = null; Client.SendDataMessage(DataMessage.Error, true); Client.SendCustomMessage(Messages.ClientListEmptyMsg, true); haderr = true; } } else { Console.WriteLine("VPN already stopped"); } if (!haderr) { Console.WriteLine("Sending offline reply"); Client.SendDataMessage(DataMessage.Offline, true); Client.SendCustomMessage(Messages.ClientListEmptyMsg, true); } } Client.SendDataMessage(DataMessage.Blank, true); handler.Shutdown(SocketShutdown.Both); handler.Close(); } } catch (Exception e) { Console.WriteLine(e); } } public static bool isProcessOnline(Process p) { if (p == null) { return false; } else { if (p.HasExited) { return false; } else { return true; } } } static void CurrentVpnProcess_Exited(object sender, EventArgs e) { Client.SendDataMessage(DataMessage.Restarting, true); Console.WriteLine("Restarting embedded process"); currentVpnProcess.Dispose(); currentVpnProcess = null; Thread.Sleep(restartDelay); if (shouldRestart) { Console.WriteLine("Sending restarting reply"); Client.SendDataMessage(DataMessage.Restarting, true); if (StartEProcess(false)) { Console.WriteLine("Sending online reply"); Client.SendDataMessage(DataMessage.Online, true); } } else { Client.SendDataMessage(DataMessage.Offline, true); Client.SendCustomMessage(Messages.ClientListEmptyMsg, true); } } static bool StartEProcess(bool reraisee) { if (shouldBeRunning) { try { currentVpnProcess = new Process { StartInfo = new ProcessStartInfo("simple-vpn", "client /etc/melon-vpn/client.cfg"), EnableRaisingEvents = true }; currentVpnProcess.Exited += CurrentVpnProcess_Exited; currentVpnProcess.Start(); Thread.Sleep(startingTime); return !currentVpnProcess.HasExited; } catch (Exception e) { //Not really fixed is it? Console.WriteLine("There was an error. But I fixed it."); Console.WriteLine("It looked like this: " + e); if (reraisee) { throw e; } } } return false; } } }