Esempio n. 1
0
        /*
         * 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
            {
                IpAddress ip = Server.IpsEntry.FirstPreferIPv4;
                if ((ip == null) || (ip.Valid == false))
                {
                    throw new Exception("Invalid ip");
                }
                routeScope = new RouteScope(ip.ToString());
                Int64 result = Platform.Instance.Ping(ip, 3);
                Engine.Instance.JobsManager.Latency.PingResult(Server, result);
            }
            catch (Exception)
            {
                Engine.Instance.JobsManager.Latency.PingResult(Server, -1);
            }
            finally
            {
                if (routeScope != null)
                {
                    routeScope.End();
                }

                lock (Engine.Instance.JobsManager.Latency.Jobs)
                {
                    Engine.Instance.JobsManager.Latency.Jobs.Remove(this);
                }
            }
        }
Esempio n. 2
0
        /*
         * 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
            {
                IpAddress ip = Server.IpsEntry.FirstPreferIPv4;
                if ((ip == null) || (ip.Valid == false))
                {
                    throw new Exception("Invalid ip");
                }
                routeScope = new RouteScope(ip.ToString());
                Int64 result = Platform.Instance.Ping(ip, Engine.Instance.Storage.GetInt("pinger.timeout"));

                if ((Engine.Instance == null) || (Engine.Instance.JobsManager == null) || (Engine.Instance.JobsManager.Latency == null))
                {
                    return;                     // Avoid unidentified crash
                }
                Engine.Instance.JobsManager.Latency.PingResult(Server, result);
            }
            catch (Exception)
            {
                if ((Engine.Instance == null) || (Engine.Instance.JobsManager == null) || (Engine.Instance.JobsManager.Latency == null))
                {
                    return;                     // Avoid unidentified crash
                }
                Engine.Instance.JobsManager.Latency.PingResult(Server, -1);
            }
            finally
            {
                if (routeScope != null)
                {
                    routeScope.End();
                }

                if ((Engine.Instance == null) || (Engine.Instance.JobsManager == null) || (Engine.Instance.JobsManager.Latency == null))
                {
                    // Avoid unidentified crash
                }
                else
                {
                    lock (Engine.Instance.JobsManager.Latency.Jobs)
                    {
                        Engine.Instance.JobsManager.Latency.Jobs.Remove(this);
                    }
                }
            }
        }
Esempio n. 3
0
        /*
         * 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
            {
                IpAddress ip = Server.IpsEntry.OnlyIPv4.First;

                /*
                 * if (Server.DisplayName == "Castor") // ClodoTemp
                 *      ip = Server.IpsEntry.OnlyIPv6.First;
                 */
                if ((ip == null) || (ip.Valid == false))
                {
                    throw new Exception("Invalid ip");
                }
                routeScope = new RouteScope(ip.ToString());
                Int64 result = Platform.Instance.Ping(ip, 3);
                Pinger.Instance.PingResult(Server, result);
            }
            catch (Exception)
            {
                Pinger.Instance.PingResult(Server, -1);
            }
            finally
            {
                if (routeScope != null)
                {
                    routeScope.End();
                }

                lock (Pinger.Instance.Jobs)
                {
                    Pinger.Instance.Jobs.Remove(this);
                }
            }
        }
Esempio n. 4
0
        public static XmlDocument FetchUrls(string title, string authPublicKey, List <string> urls, 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);

            string firstError = "";
            int    hostN      = 0;

            foreach (string url in urls)
            {
                string host = Utils.HostFromUrl(url);

                hostN++;
                if (IpAddress.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.FetchUrl(authPublicKey, url, 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.Logs.Log(LogType.Verbose, MessagesFormatter.Format(Messages.ExchangeTryFailed, title, hostN.ToString(), info));
                    }

                    if (firstError == "")
                    {
                        firstError = info;
                    }
                }
            }

            throw new Exception(firstError);
        }
Esempio n. 5
0
        /*
        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("pinger.always"); // 2.6
                routeScope = new RouteScope(Server.IpEntry);

                Int64 result = Platform.Instance.Ping(Server.IpEntry, 3);
                Pinger.Instance.PingResult(Server, result);
                /*

                // 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 = 2000;
                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);
                }
            }
        }
Esempio n. 6
0
        public override void OnRun()
        {
            CancelRequested = false;

            Engine.ConnectedSessionStatsRead = 0;
            Engine.ConnectedSessionStatsWrite = 0;

            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;

                Engine.ConnectedVpnStatsRead = 0;
                Engine.ConnectedVpnStatsWrite = 0;

                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 + " " + MessagesFormatter.Format(Messages.WaitingLatencyTestsStep, i.ToString());
                            if (lastWaitingMessage != nextWaitingMessage)
                            {
                                lastWaitingMessage = nextWaitingMessage;
                                Engine.WaitMessageSet(nextWaitingMessage, true);
                            }

                            Sleep(100);
                        }
                    }

                    if (CancelRequested)
                        continue;

                    m_openVpnManagementCommands.Clear();

                    Engine.CurrentServer = Engine.NextServer;
                    Engine.NextServer = null;

                    string forceServer = Engine.Storage.Get("server");
                    if (forceServer != "")
                    {
                        Engine.CurrentServer = Engine.PickServerByName(forceServer);
                    }
                    else
                    {
                        if (Engine.CurrentServer == null)
                            if (Engine.Storage.GetBool("servers.locklast"))
                                Engine.CurrentServer = Engine.PickServer(sessionLastServer);

                        if (Engine.CurrentServer == null)
                            Engine.CurrentServer = Engine.PickServer();
                    }

                    if (Engine.CurrentServer == null)
                    {
                        allowed = false;
                        Engine.Logs.Log(LogType.Fatal, "No server available.");
                        RequestStop();
                    }

                    /*
                    string protocol = Engine.Storage.Get("mode.protocol").ToUpperInvariant();
                    int port = Engine.Storage.GetInt("mode.port");
                    int alt = Engine.Storage.GetInt("mode.alt");

                    if (Engine.CurrentServer != null)
                    {
                        if (protocol == "AUTO")
                        {
                            protocol = Engine.CurrentServer.Provider.GetKeyValue("mode_protocol", "UDP");
                            string proxyMode = Engine.Storage.GetLower("proxy.mode");
                            if (proxyMode != "none")
                                protocol = "TCP";
                            port = Conversions.ToInt32(Engine.CurrentServer.Provider.GetKeyValue("mode_port", "443"));
                            alt = Conversions.ToInt32(Engine.CurrentServer.Provider.GetKeyValue("mode_alt", "0"));
                        }
                    }

                    if (protocol == "SSH")
                    {
                        connectionMode = "SSH";
                        m_proxyPort = Engine.Storage.GetInt("ssh.port");
                        if (m_proxyPort == 0)
                            m_proxyPort = RandomGenerator.GetInt(1024, 64 * 1024);
                    }
                    else if (protocol == "SSL")
                    {
                        connectionMode = "SSL";
                        m_proxyPort = Engine.Storage.GetInt("ssl.port");
                        if (m_proxyPort == 0)
                            m_proxyPort = RandomGenerator.GetInt(1024, 64 * 1024);
                    }
                    else
                    {
                        connectionMode = "OpenVPN";
                        m_proxyPort = 0;
                    }
                    */

                    // 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)
                    {
                        if (Engine.CurrentServer.Provider is Providers.Service)
                        {
                            Providers.Service service = Engine.CurrentServer.Provider as Providers.Service;
                            if (service.SupportConnect)
                            {
                                Engine.WaitMessageSet(Messages.AuthorizeConnect, true);
                                Engine.Logs.Log(LogType.Info, Messages.AuthorizeConnect);

                                Dictionary<string, string> parameters = new Dictionary<string, string>();
                                parameters["act"] = "connect";
                                parameters["server"] = Engine.CurrentServer.ProviderName;
                                /* // 2.11.4
                                parameters["protocol"] = protocol;
                                parameters["port"] = port.ToString();
                                parameters["alt"] = alt.ToString();
                                */

                                XmlDocument xmlDoc = null;
                                try
                                {
                                    xmlDoc = service.Fetch(Messages.AuthorizeConnect, parameters);
                                }
                                catch (Exception e)
                                {
                                    // Note: If failed, continue anyway.
                                    Engine.Logs.Log(LogType.Warning, MessagesFormatter.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.Logs.Log(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;

                    try
                    {
                        BuildOVPN();
                    }
                    catch(Exception e)
                    {
                        Engine.Logs.Log(e);
                        allowed = false;
                        SetReset("ERROR");
                    }

                    if (allowed)
                    {
                        sessionLastServer = Engine.CurrentServer.Code;
                        Engine.Storage.Set("servers.last", Engine.CurrentServer.Code);

                        routeScope = new RouteScope(Engine.ConnectedEntryIP); // Clodo: Urgent, may not work under some OS with NetLock active. Try to add the RouteScope when detecting protocol from OpenVPN logs.

                        Engine.RunEventCommand("vpn.pre");

                        string connectingMessage = MessagesFormatter.Format(Messages.ConnectionConnecting, Engine.CurrentServer.GetNameWithLocation());
                        Engine.WaitMessageSet(connectingMessage, true);
                        Engine.Logs.Log(LogType.InfoImportant, connectingMessage);

                        if (m_ovpn.Protocol == "SSH")
                        {
                            StartSshProcess();
                        }
                        else if (m_ovpn.Protocol == "SSL")
                        {
                            StartSslProcess();
                        }
                        //else if ( (Engine.ConnectedProtocol == "UDP") || (Engine.ConnectedProtocol == "TCP") )
                        else // 2.11.4
                        {
                            StartOpenVpnProcess();
                        }

                        int waitingSleep = 100; // To avoid CPU stress

                        SetReset("");

                        // -----------------------------------
                        // Phase 2: Waiting connection
                        // -----------------------------------

                        for (; ; )
                        {
                            if ((m_processOpenVpn != null) && (m_processOpenVpn.ReallyExited)) // 2.2
                                SetReset("ERROR");
                            if( (m_processProxy != null) && (m_processProxy.ReallyExited) ) // 2.2
                                SetReset("ERROR");

                            if (Engine.IsConnected())
                                break;

                            if (m_reset != "")
                                break;

                            Sleep(waitingSleep);
                        }

                        if(m_reset == "")
                            oneConnectionReached = true;

                        // -----------------------------------
                        // 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 tunRead = 0;
                                            Int64 tunWrite = 0;

                                            tunRead += m_interfaceTun.GetIPv4Statistics().BytesReceived;
                                            tunWrite += m_interfaceTun.GetIPv4Statistics().BytesSent;

                                            if (InterfaceTunBytesReadInitial == -1)
                                            {
                                                InterfaceTunBytesReadInitial = tunRead;
                                                InterfaceTunBytesWriteInitial = tunWrite;
                                            }
                                            tunRead -= InterfaceTunBytesReadInitial;
                                            tunWrite -= InterfaceTunBytesWriteInitial;

                                            UpdateBytesStats(tunRead, tunWrite);
                                        }
                                    }
                                    else if (Platform.Instance.GetTunStatsMode() == "OpenVpnManagement")
                                    {
                                        SendManagementCommand("status");
                                    }
                                }

                                // Need stop?
                                bool StopRequest = false;

                                if (m_reset == "RETRY")
                                {
                                    StopRequest = true;
                                }
                                else if (m_reset == "ERROR")
                                {
                                    //Engine.CurrentServer.Penality += Engine.Storage.GetInt("advanced.penality_on_error"); // Removed in 2.11
                                    StopRequest = true;
                                }
                                else if (m_reset == "FATAL")
                                {
                                    StopRequest = true;
                                }

                                if (Engine.NextServer != null)
                                {
                                    SetReset("SWITCH"); // 2.11.8
                                    StopRequest = true;
                                }

                                if (Engine.SwitchServer != false)
                                {
                                    Engine.SwitchServer = false;
                                    SetReset("SWITCH"); // 2.11.8
                                    StopRequest = true;
                                }

                                if (CancelRequested)
                                    StopRequest = true;

                                if (StopRequest)
                                    break;

                                Sleep(waitingSleep);
                            }
                        }

                        if (m_reset == "ERROR") // Added in 2.11
                        {
                            Engine.CurrentServer.Penality += Engine.Storage.GetInt("advanced.penality_on_error");
                        }

                        // -----------------------------------
                        // Phase 4 - Start disconnection
                        // -----------------------------------

                        Engine.SetConnected(false);

                        Engine.WaitMessageSet(Messages.ConnectionDisconnecting, false);
                        Engine.Logs.Log(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.Logs.Log(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.Logs.Log(LogType.Verbose, Messages.ConnectionStop);

                        Engine.RunEventCommand("vpn.down");

                        Platform.Instance.OnRouteDefaultRemoveRestore();

                        Platform.Instance.OnDnsSwitchRestore();

                        // Closing temporary files
                        if (m_fileSshKey != null)
                        {
                            m_fileSshKey.Close();
                            m_fileSshKey = null;
                        }
                        if (m_fileSslCrt != null)
                        {
                            m_fileSslCrt.Close();
                            m_fileSslCrt = null;
                        }
                        if (m_fileSslConfig != null)
                        {
                            m_fileSslConfig.Close();
                            m_fileSslConfig = null;
                        }
                        if (m_fileOvpn != null)
                        {
                            m_fileOvpn.Close();
                            m_fileOvpn = null;
                        }
                        if (m_fileProxyAuth != null)
                        {
                            m_fileProxyAuth.Close();
                            m_fileProxyAuth = null;
                        }
                        if (m_filePasswordAuth != null)
                        {
                            m_filePasswordAuth.Close();
                            m_filePasswordAuth = null;
                        }
                    }

                }
                catch (Exception e)
                {
                    // Warning: Avoid to reach this catch: unpredicable status of running processes.
                    Engine.SetConnected(false);

                    Engine.Logs.Log(LogType.Warning, e);
                }

                if (routeScope != null)
                    routeScope.End();

                if (m_programScope != null)
                    m_programScope.End();

                if (m_interfaceScope != null)
                    m_interfaceScope.End();

                if (Engine.Instance.Storage.GetBool("batch"))
                {
                    Engine.Instance.RequestStop();
                    break;
                }

                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;
                }
                else if (m_reset == "FATAL")
                {
                    Engine.Instance.Disconnect();
                    break;
                }

                if (waitingSecs > 0)
                {
                    for (int i = 0; i < waitingSecs; i++)
                    {
                        Engine.WaitMessageSet(MessagesFormatter.Format(waitingMessage, (waitingSecs - i).ToString()), true);
                        //Engine.Log(Engine.LogType.Verbose, waitingMessage);
                        if (CancelRequested)
                            break;

                        Sleep(1000);
                    }
                }
            }

            if (oneConnectionReached == false)
            {
                if (CancelRequested)
                {
                    Engine.Logs.Log(LogType.Info, Messages.SessionCancel);
                }
                else
                {
                    Engine.Logs.Log(LogType.Error, Messages.SessionFailed);
                }
            }

            Engine.Instance.WaitMessageClear();

            Engine.CurrentServer = null;
        }
Esempio n. 7
0
        public static XmlDocument FetchUrls(string title, string authPublicKey, List<string> urls, 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);

            string firstError = "";
            int hostN = 0;
            foreach (string url in urls)
            {
                string host = Utils.HostFromUrl(url);

                hostN++;
                if (IpAddress.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.FetchUrl(authPublicKey, url, 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.Logs.Log(LogType.Verbose, MessagesFormatter.Format(Messages.ExchangeTryFailed, title, hostN.ToString(), info));

                    if (firstError == "")
                        firstError = info;
                }
            }

            throw new Exception(firstError);
        }