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 = false; private static bool isRestarting = false; private static int startingTime = 3000; private static int restartDelay = 250; private static DaemonServer _srv; private static DaemonClientMultiplexor _mlt; private static string lastClientUpdate = Messages.EOF; public static void StartServer() { _srv = new DaemonServer(); _mlt = new DaemonClientMultiplexor(_srv); _mlt.clientMessageReceived += clientMessageReceived; _srv.start(); } public static bool isProcessOnline(Process p) { if (p == null) { return false; } else { if (p.HasExited) { return false; } else { return true; } } } static void clientMessageReceived(object sender, string data) { try { if (data.StartsWith(Messages.ClientListStartMsg, StringComparison.CurrentCulture) && shouldBeRunning) { lastClientUpdate = data; _mlt.SendCustomMessage(lastClientUpdate); } else if (data == Messages.RestartOnMsg) { shouldRestart = true; _mlt.SendDataMessage(DataMessage.RestartOn); } else if (data == Messages.RestartOffMsg) { shouldRestart = false; _mlt.SendDataMessage(DataMessage.RestartOff); } else if (data == Messages.StatusMsg) { Console.WriteLine("Status requested"); if (isProcessOnline(currentVpnProcess) || shouldBeRunning) { if (isRestarting) { Console.WriteLine("Sending response: restarting"); _mlt.SendDataMessage(DataMessage.Restarting); _mlt.SendCustomMessage(lastClientUpdate); } else { Console.WriteLine("Sending response: online"); _mlt.SendDataMessage(DataMessage.Online); _mlt.SendCustomMessage(lastClientUpdate); } } else { Console.WriteLine("Sending response: offline"); _mlt.SendDataMessage(DataMessage.Offline); _mlt.SendCustomMessage(Messages.ClientListEmptyMsg); } _mlt.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"); _mlt.SendDataMessage(DataMessage.Starting); if (StartEProcess(true)) { Console.WriteLine("Sending online reply"); _mlt.SendDataMessage(DataMessage.Online); currentVpnProcess.EnableRaisingEvents = true; } else { throw new InvalidOperationException("Client crashed!"); } } 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; _mlt.SendDataMessage(DataMessage.Error); _mlt.SendCustomMessage(Messages.ClientListEmptyMsg); } } 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; _mlt.SendDataMessage(DataMessage.Error); _mlt.SendCustomMessage(Messages.ClientListEmptyMsg); haderr = true; } } else { Console.WriteLine("VPN already stopped"); } if (!haderr) { Console.WriteLine("Sending offline reply"); _mlt.SendDataMessage(DataMessage.Offline); _mlt.SendCustomMessage(Messages.ClientListEmptyMsg); } } _mlt.SendDataMessage(DataMessage.Blank); } catch (Exception e) { Console.WriteLine(e); } } static void CurrentVpnProcess_Exited(object sender, EventArgs e) { Console.WriteLine("Restarting embedded process"); currentVpnProcess.Dispose(); currentVpnProcess = null; Thread.Sleep(restartDelay); bool imonline = false; isRestarting = true; while (shouldRestart && shouldBeRunning) { Console.WriteLine("Sending restarting reply"); _mlt.SendDataMessage(DataMessage.Restarting); if (StartEProcess(false)) { Console.WriteLine("Sending online reply"); _mlt.SendDataMessage(DataMessage.Online); currentVpnProcess.EnableRaisingEvents = true; imonline = true; break; } else { currentVpnProcess.Dispose(); currentVpnProcess = null; Thread.Sleep(restartDelay); } } isRestarting = false; if (! imonline) { shouldBeRunning = false; Console.WriteLine("Sending offline reply"); _mlt.SendDataMessage(DataMessage.Offline); _mlt.SendCustomMessage(Messages.ClientListEmptyMsg); } } static bool StartEProcess(bool reraisee) { if (shouldBeRunning) { try { currentVpnProcess = new Process { StartInfo = new ProcessStartInfo("simple-vpn", "client /etc/melon-vpn/client.cfg"), EnableRaisingEvents = false }; 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; } } }