/* public void Start() { T = new System.Threading.Thread(new ThreadStart(this.Run)); T.Priority = ThreadPriority.Lowest; T.Start(); } */ public void Run() { RouteScope routeScope = null; try { //bool alwaysRun = Engine.Instance.Storage.GetBool("advanced.pinger.always"); // 2.6 routeScope = new RouteScope(Server.IpEntry); // Ping Ping pingSender = new Ping(); PingOptions options = new PingOptions(); // Use the default Ttl value which is 128, // but change the fragmentation behavior. options.DontFragment = true; // Create a buffer of 32 bytes of data to be transmitted. byte[] buffer = RandomGenerator.GetBuffer(32); int timeout = 5000; PingReply reply = pingSender.Send(Server.IpEntry, timeout, buffer, options); Pinger.Instance.PingResult(Server, reply); } catch (Exception) { Pinger.Instance.PingResult(Server, -1); } finally { if (routeScope != null) { routeScope.End(); } lock (Pinger.Instance.Jobs) { Pinger.Instance.Jobs.Remove(this); } } }
public static XmlDocument Fetch(string title, Dictionary<string, string> parameters) { parameters["login"] = Engine.Instance.Storage.Get("login"); parameters["password"] = Engine.Instance.Storage.Get("password"); parameters["system"] = Platform.Instance.GetSystemCode(); parameters["version"] = Constants.VersionInt.ToString(CultureInfo.InvariantCulture); List<string> hosts = new List<string>(); if (Engine.Instance.Storage.Manifest != null) { XmlNodeList nodesHosts = Engine.Instance.Storage.Manifest.SelectNodes("//hosts/host"); foreach (XmlNode nodeHost in nodesHosts) { hosts.Add(nodeHost.Attributes["address"].Value); } } // Debugging // hosts.Clear(); // hosts.Add("invalidhostname.airvpn.org"); // hosts.Add("54.246.124.152"); string firstError = ""; int hostN = 0; foreach (string host in hosts) { hostN++; if (Utils.IsIP(host) == false) { // If locked network are enabled, skip the hostname and try only by IP. // To avoid DNS issue (generally, to avoid losing time). if (Engine.Instance.NetworkLockManager.IsDnsResolutionAvailable(host) == false) continue; } try { RouteScope routeScope = new RouteScope(host); XmlDocument xmlDoc = AirExchange.FetchHost(host, parameters); routeScope.End(); if (xmlDoc == null) throw new Exception("No answer."); if (xmlDoc.DocumentElement.Attributes["error"] != null) throw new Exception(xmlDoc.DocumentElement.Attributes["error"].Value); return xmlDoc; } catch (Exception e) { string info = e.Message; string proxyMode = Engine.Instance.Storage.Get("proxy.mode").ToLowerInvariant(); string proxyAuth = Engine.Instance.Storage.Get("proxy.auth").ToLowerInvariant(); if (proxyMode != "none") info += ", with '" + proxyMode + "' proxy and '" + proxyAuth + "' auth"; if (Engine.Instance.Storage.GetBool("advanced.expert")) Engine.Instance.Log(Engine.LogType.Verbose, Messages.Format(Messages.ExchangeTryFailed, title, hostN.ToString(), info)); if (firstError == "") firstError = info; } } throw new Exception(firstError); }
public static XmlDocument Fetch(string title, Dictionary <string, string> parameters) { parameters["login"] = Engine.Instance.Storage.Get("login"); parameters["password"] = Engine.Instance.Storage.Get("password"); parameters["system"] = Platform.Instance.GetSystemCode(); parameters["version"] = Constants.VersionInt.ToString(CultureInfo.InvariantCulture); List <string> hosts = new List <string>(); if (Engine.Instance.Storage.Manifest != null) { XmlNodeList nodesHosts = Engine.Instance.Storage.Manifest.SelectNodes("//hosts/host"); foreach (XmlNode nodeHost in nodesHosts) { hosts.Add(nodeHost.Attributes["address"].Value); } } // Debugging /* * hosts.Clear(); * hosts.Add("invalidhostname.airvpn.org"); * hosts.Add("54.93.175.114"); */ string firstError = ""; int hostN = 0; foreach (string host in hosts) { hostN++; if (Utils.IsIP(host) == false) { // If locked network are enabled, skip the hostname and try only by IP. // To avoid DNS issue (generally, to avoid losing time). if (Engine.Instance.NetworkLockManager.IsDnsResolutionAvailable(host) == false) { continue; } } try { RouteScope routeScope = new RouteScope(host); XmlDocument xmlDoc = AirExchange.FetchHost(host, parameters); routeScope.End(); if (xmlDoc == null) { throw new Exception("No answer."); } if (xmlDoc.DocumentElement.Attributes["error"] != null) { throw new Exception(xmlDoc.DocumentElement.Attributes["error"].Value); } return(xmlDoc); } catch (Exception e) { string info = e.Message; string proxyMode = Engine.Instance.Storage.Get("proxy.mode").ToLowerInvariant(); string proxyAuth = Engine.Instance.Storage.Get("proxy.auth").ToLowerInvariant(); if (proxyMode != "none") { info += ", with '" + proxyMode + "' proxy and '" + proxyAuth + "' auth"; } Engine.Instance.Log(Engine.LogType.Verbose, Messages.Format(Messages.ExchangeTryFailed, title, hostN.ToString(), info)); if (firstError == "") { firstError = e.Message; } } } throw new Exception(firstError); }
public override void OnRun() { CancelRequested = false; string sessionLastServer = ""; bool oneConnectionReached = false; for (; CancelRequested == false; ) { RouteScope routeScope = null; bool allowed = true; string waitingMessage = ""; int waitingSecs = 0; m_processOpenVpn = null; m_processProxy = null; try { // ----------------------------------- // Phase 1: Initialization and start // ----------------------------------- if ((Engine.NextServer == null) && (Pinger.Instance.GetEnabled()) && (Engine.PingerInvalid() != 0)) { string lastWaitingMessage = ""; for (; ; ) { if (CancelRequested) break; int i = Engine.PingerInvalid(); if (i == 0) break; string nextWaitingMessage = Messages.WaitingLatencyTestsTitle + " " + Messages.Format(Messages.WaitingLatencyTestsStep, i.ToString()); if (lastWaitingMessage != nextWaitingMessage) { lastWaitingMessage = nextWaitingMessage; Engine.WaitMessageSet(nextWaitingMessage, true); } Sleep(100); } } if (CancelRequested) continue; m_openVpnManagementCommands.Clear(); string protocol = Engine.Storage.Get("mode.protocol").ToUpperInvariant(); int port = Engine.Storage.GetInt("mode.port"); int alt = Engine.Storage.GetInt("mode.alt"); if (protocol == "AUTO") { protocol = Engine.Storage.GetManifestKeyValue("mode_protocol", "UDP"); port = Conversions.ToInt32(Engine.Storage.GetManifestKeyValue("mode_port", "443")); alt = Conversions.ToInt32(Engine.Storage.GetManifestKeyValue("mode_alt", "0")); } if (protocol == "SSH") { m_proxyPort = Engine.Storage.GetInt("ssh.port"); if (m_proxyPort == 0) m_proxyPort = RandomGenerator.GetInt(1024, 64 * 1024); } else if (protocol == "SSL") { m_proxyPort = Engine.Storage.GetInt("ssl.port"); if (m_proxyPort == 0) m_proxyPort = RandomGenerator.GetInt(1024, 64 * 1024); } else { m_proxyPort = 0; } Engine.CurrentServer = Engine.NextServer; Engine.NextServer = null; if (Engine.Storage.Get("server") != "") { Engine.CurrentServer = Engine.PickServer(Engine.Storage.Get("server"), true); } else { if (Engine.CurrentServer == null) if (Engine.Storage.GetBool("servers.locklast")) Engine.CurrentServer = Engine.PickServer(sessionLastServer, false); if (Engine.CurrentServer == null) Engine.CurrentServer = Engine.PickServer(); } if (Engine.CurrentServer == null) { allowed = false; Engine.Log(Core.Engine.LogType.Fatal, "No server available."); RequestStop(); } // Checking auth user status. // Only to avoid a generic AUTH_FAILED. For that we don't report here for ex. the sshtunnel keys. if (allowed) { Engine.WaitMessageSet(Messages.AuthorizeConnect, true); Engine.Log(Engine.LogType.Info, Messages.AuthorizeConnect); Dictionary<string, string> parameters = new Dictionary<string, string>(); parameters["act"] = "connect"; parameters["server"] = Engine.CurrentServer.Name; parameters["protocol"] = protocol; parameters["port"] = port.ToString(); parameters["alt"] = alt.ToString(); XmlDocument xmlDoc = null; try { xmlDoc = AirExchange.Fetch(Messages.AuthorizeConnect, parameters); } catch (Exception e) { // Note: If failed, continue anyway. Engine.Log(Engine.LogType.Warning, Messages.Format(Messages.AuthorizeConnectFailed, e.Message)); } if (xmlDoc != null) { string userMessage = Utils.XmlGetAttributeString(xmlDoc.DocumentElement, "message", ""); if (userMessage != "") { allowed = false; string userMessageAction = Utils.XmlGetAttributeString(xmlDoc.DocumentElement, "message_action", ""); if (userMessageAction == "stop") { Engine.Log(Core.Engine.LogType.Fatal, userMessage); Engine.Disconnect(); // 2.8 RequestStop(); } else if (userMessageAction == "next") { Engine.CurrentServer.Penality += Engine.Storage.GetInt("advanced.penality_on_error"); waitingMessage = userMessage + ", next in {1} sec."; waitingSecs = 5; } else { waitingMessage = userMessage + ", retry in {1} sec."; waitingSecs = 10; } } } } if (CancelRequested) continue; if (allowed) { sessionLastServer = Engine.CurrentServer.Name; Engine.Storage.Set("servers.last", Engine.CurrentServer.Name); if (Engine.CurrentServer.ServerType == 2) { // Routing servers have only 443-UDP-1ip protocol = "UDP"; port = 443; alt = 0; } routeScope = new RouteScope(Engine.ConnectedEntryIP); Engine.RunEventCommand("vpn.pre"); string connectingMessage = Messages.Format(Messages.ConnectionConnecting, Engine.CurrentServer.PublicName, Engine.CurrentServer.CountryName, Engine.CurrentServer.Location); Engine.WaitMessageSet(connectingMessage, true); Engine.Log(Engine.LogType.InfoImportant, connectingMessage); Engine.BuildOVPN(protocol, port, alt, m_proxyPort); if (protocol == "SSH") { StartSshProcess(); } else if (protocol == "SSL") { StartSslProcess(); } else if ((protocol == "TCP") || (protocol == "UDP") || (protocol == "TOR")) { StartOpenVpnProcess(); } int waitingSleep = 100; // To avoid CPU stress m_reset = ""; // ----------------------------------- // Phase 2: Waiting connection // ----------------------------------- for (; ; ) { if( (m_processOpenVpn != null) && (m_processOpenVpn.ReallyExited) ) // 2.2 m_reset = "ERROR"; if( (m_processProxy != null) && (m_processProxy.ReallyExited) ) // 2.2 m_reset = "ERROR"; if (Engine.IsConnected()) break; if (m_reset != "") break; Sleep(waitingSleep); } if(m_reset == "") oneConnectionReached = true; if( (m_reset == "") && (Engine.Instance.Storage.GetBool("advanced.testmode")) ) { m_reset = "STOP"; } // ----------------------------------- // Phase 3 - Running // ----------------------------------- if (m_reset == "") { for (; ; ) { int timeNow = Utils.UnixTimeStamp(); if (Engine.IsConnected() == false) throw new Exception("Unexpected."); ProcessOpenVpnManagement(); if (timeNow - m_timeLastStatus >= 1) { m_timeLastStatus = timeNow; // Update traffic stats if (Storage.Simulate) { Engine.Instance.Stats.Charts.Hit(15354, 2525); Engine.OnRefreshUi(Core.Engine.RefreshUiMode.Stats); } else if(Platform.Instance.GetTunStatsMode() == "NetworkInterface") { if (m_interfaceTun != null) { Int64 read = m_interfaceTun.GetIPv4Statistics().BytesReceived; Int64 write = m_interfaceTun.GetIPv4Statistics().BytesSent; if (Engine.ConnectedLastRead != -1) { int delta = Engine.ConnectedLastStatsTick.Reset(); if (delta > 0) { Engine.ConnectedLastDownloadStep = (1000 * (read - Engine.ConnectedLastRead)) / delta; Engine.ConnectedLastUploadStep = (1000 * (write - Engine.ConnectedLastWrite)) / delta; } } Engine.ConnectedLastRead = read; Engine.ConnectedLastWrite = write; Engine.Instance.Stats.Charts.Hit(Engine.ConnectedLastDownloadStep, Engine.ConnectedLastUploadStep); Engine.OnRefreshUi(Core.Engine.RefreshUiMode.Stats); } } else if (Platform.Instance.GetTunStatsMode() == "OpenVpnManagement") { SendManagementCommand("status"); } } // Need stop? bool StopRequest = false; if (m_reset == "RETRY") { StopRequest = true; } if (m_reset == "ERROR") { Engine.CurrentServer.Penality += Engine.Storage.GetInt("advanced.penality_on_error"); StopRequest = true; } if (Engine.NextServer != null) { StopRequest = true; } if (Engine.SwitchServer != false) { Engine.SwitchServer = false; StopRequest = true; } if (CancelRequested) StopRequest = true; if (StopRequest) break; Sleep(waitingSleep); } } // ----------------------------------- // Phase 4 - Start disconnection // ----------------------------------- Engine.SetConnected(false); Engine.WaitMessageSet(Messages.ConnectionDisconnecting, false); Engine.Log(Engine.LogType.InfoImportant, Messages.ConnectionDisconnecting); if (Storage.Simulate) { if (m_processOpenVpn.ReallyExited == false) m_processOpenVpn.Kill(); } // ----------------------------------- // Phase 5 - Waiting disconnection // ----------------------------------- TimeDelta DeltaSigTerm = null; for (; ; ) { try { // As explained here: http://stanislavs.org/stopping-command-line-applications-programatically-with-ctrl-c-events-from-net/ // there isn't any .Net/Mono clean method to send a signal term to a Windows console-only application. So a brutal Kill is performed when there isn't any alternative. // TODO: Maybe optimized under Linux. // Simulation process if ((Storage.Simulate) && (m_processOpenVpn != null) && (m_processOpenVpn.ReallyExited == false)) m_processOpenVpn.Kill(); // OpenVPN process completed, but management socket still opened. Strange, but happen. Closing socket. if ((m_processOpenVpn != null) && (m_openVpnManagementSocket != null) && (m_processOpenVpn.ReallyExited == true) && (m_openVpnManagementSocket.Connected)) m_openVpnManagementSocket.Close(); // OpenVPN process still exists, but management socket is not connected. We can't tell to OpenVPN to do a plain disconnection, force killing. if ((m_processOpenVpn != null) && (m_processOpenVpn.ReallyExited == false)) { if ((m_openVpnManagementSocket == null) || (m_openVpnManagementSocket.Connected == false)) m_processOpenVpn.Kill(); } // Proxy (SSH/SSL) process if ((m_processProxy != null) && (m_processOpenVpn != null) && (m_processProxy.ReallyExited == false) && (m_processOpenVpn.ReallyExited == true)) { m_processProxy.Kill(); } // Start a clean disconnection if ((m_processOpenVpn != null) && (m_openVpnManagementSocket != null) && (m_processOpenVpn.ReallyExited == false) && (m_openVpnManagementSocket.Connected)) { bool sendSignal = false; if (DeltaSigTerm == null) { DeltaSigTerm = new TimeDelta(); sendSignal = true; } else if (DeltaSigTerm.Elapsed(10000)) // Try a SIGTERM every 10 seconds sendSignal = true; if(sendSignal) { SendManagementCommand("signal SIGTERM"); ProcessOpenVpnManagement(); } } } catch (Exception e) { Engine.Log(Core.Engine.LogType.Warning, e); } bool exit = true; if ((m_openVpnManagementSocket != null) && (m_openVpnManagementSocket.Connected)) exit = false; if ((m_processProxy != null) && (m_processProxy.ReallyExited == false)) exit = false; if ((m_processOpenVpn != null) && (m_processOpenVpn.ReallyExited == false)) exit = false; if (exit) break; Sleep(waitingSleep); } // ----------------------------------- // Phase 6: Cleaning, waiting before retry. // ----------------------------------- Engine.Log(Engine.LogType.Verbose, Messages.ConnectionStop); Engine.RunEventCommand("vpn.down"); Platform.Instance.OnRouteDefaultRemoveRestore(); Platform.Instance.OnDnsSwitchRestore(); // Closing temporary files if (m_fileSshKey != null) m_fileSshKey.Close(); if (m_fileSslCrt != null) m_fileSslCrt.Close(); if (m_fileSslConfig != null) m_fileSslConfig.Close(); if (m_fileOvpn != null) m_fileOvpn.Close(); } } catch (Exception e) { // Warning: Avoid to reach this catch: unpredicable status of running processes. Engine.SetConnected(false); Engine.Log(Core.Engine.LogType.Warning, e); } if (routeScope != null) routeScope.End(); if (m_reset == "AUTH_FAILED") { waitingMessage = "Auth failed, retry in {1} sec."; waitingSecs = 10; } else if (m_reset == "ERROR") { waitingMessage = "Restart in {1} sec."; waitingSecs = 3; } if (Engine.Instance.Storage.GetBool("advanced.testmode")) { Engine.Instance.RequestStop(); break; } if (waitingSecs > 0) { for (int i = 0; i < waitingSecs; i++) { Engine.WaitMessageSet(Messages.Format(waitingMessage, (waitingSecs - i).ToString()), true); //Engine.Log(Engine.LogType.Verbose, waitingMessage); if (CancelRequested) break; Sleep(1000); } } } if (oneConnectionReached == false) { if (CancelRequested) { Engine.Log(Engine.LogType.Info, Messages.SessionCancel); } else { Engine.Log(Engine.LogType.Error, Messages.SessionFailed); } } Engine.Instance.WaitMessageClear(); Engine.CurrentServer = null; }