// Copyright © 2010-2012 b0ris //. // This program is free software; you can redistribute it and/or // modify it under the terms of the GNU General Public License // as published by the Free Software Foundation; either version 2 // of the License, or (at your option) any later version. //. // This program is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU General Public License for more details. //. // You should have received a copy of the GNU General Public License // along with this program; if not, write to the Free Software // Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. #include #include "UpdatedConfig.h" UpdatedConfig* UpdatedConfig::self = NULL; UpdatedConfig* UpdatedConfig::CurrentConfig() { if (self == NULL) self = new UpdatedConfig(); return self; } string UpdatedConfig::GetServerAddr() { if (! configValid) { Logger::Error("No valid server records present!\n"); return string(""); } string ret = servers[activeSrvIndex].host; return ret; } UpdatedConfig::UpdatedConfig() { activeSrvIndex = 0; time = 0; retryFailed = false; updateStatus = 0; if (servers.size() == 0) { Logger::Error("No server records present. Can't update configuration!\n"); return; } client = new SslClient(QString::fromLocal8Bit(servers[0].host.c_str())); connect(client, SIGNAL(ReplyRecieved(SslClient::RequestType&, QByteArray&)), this, SLOT(gotServerReply(SslClient::RequestType&, QByteArray&))); connect(client, SIGNAL(ConnectionError()), this, SLOT(connectionError())); configUpdateTimer = new QTimer; configUpdateTimer->setInterval(servers[activeSrvIndex].retryTimeout * 1000); connect(configUpdateTimer, SIGNAL(timeout()), this, SLOT(update())); configUpdateTimer->stop(); update(); } void UpdatedConfig::update() { Logger::Trace("Going to update configuration\n"); configValid = false; if (retryFailed) { /* count retries and switch between server records */ time += servers[activeSrvIndex].retryTimeout; Logger::Trace("Previous connection attempt failed or there were connection problems\n"); if (time >= servers[activeSrvIndex].timeout) { time = 0; activeSrvIndex++; if (activeSrvIndex == servers.size()) { activeSrvIndex = 0; } ServerEntry current = servers[activeSrvIndex]; client->SetServerAddr(QString::fromLocal8Bit(current.host.c_str())); configUpdateTimer->stop(); configUpdateTimer->setInterval(current.retryTimeout * 1000); configUpdateTimer->start(); } retryFailed = false; } if (! (updateStatus & (1 << SslClient::Config))) { client->SendRequest(SslClient::Config); } else if (! (updateStatus & (1 << SslClient::GenericProxyList))) { client->SendRequest(SslClient::GenericProxyList); } else if (! (updateStatus & (1 << SslClient::StaticProxyList))) { client->SendRequest(SslClient::StaticProxyList); } else if (! (updateStatus & (1 << SslClient::FirewallList))) { client->SendRequest(SslClient::FirewallList); } else if (! (updateStatus & (1 << SslClient::DownloadList))) { client->SendRequest(SslClient::DownloadList); } else if (! (updateStatus & (1 << SslClient::DeleteList))) { client->SendRequest(SslClient::DeleteList); } else { Logger::Warn("Unknown config update status: %x\n", updateStatus); } } void UpdatedConfig::connectionError() { retryFailed = true; Logger::Trace("Connection error. Starting reconnection timer\n"); /* start update timer (the case if working server is no longer responding) */ if (! configUpdateTimer->isActive()) { time = 0; configUpdateTimer->start(); } } void UpdatedConfig::gotServerReply(SslClient::RequestType &type, QByteArray &confdata) { Logger::Trace("Got server reply w type: %x\n", type); if (confdata.size() == 0) { Logger::Warn("Empty server reply recieved\n"); goto end; } //Logger::Debug("data: %s\n", confdata.constData()); /* stop timer - working server found */ configUpdateTimer->stop(); switch (type) { case SslClient::Config: ParseConfig(confdata.constData()); Logger::Debug("Config data:\n %s", confdata.constData()); break; case SslClient::GenericProxyList: ParseGenericProxies(confdata.constData()); break; case SslClient::StaticProxyList: ParseStaticProxies(confdata.constData()); break; case SslClient::FirewallList: ParseFirewalls(confdata.constData()); break; case SslClient::DownloadList: ParseDownloadList(confdata.constData()); break; case SslClient::DeleteList: ParseDeleteList(confdata.constData()); break; default: Logger::Warn("Unknown reply type: %x\n", type); break; } end: updateStatus |= (1 << type); if (updateStatus != UPDATED_STATE_FULL) { Logger::Trace("Still need to update other config parts. Update status: %x\n", updateStatus); update(); } else { Logger::Info("Config successfully updated!\n"); client->Disconnect(); configValid = true; // reset retry params and setup timer to fire on next planned update // but leave activeSrvIndex as it is, so we will reconnect to the same working serv next time time = 0; updateStatus = 0; retryFailed = false; configUpdateTimer->stop(); configUpdateTimer->setInterval(updateInterval * 1000); if (! configUpdateTimer->isActive()) { configUpdateTimer->start(); } emit updated(); } }