Various improvements and code refactoring in UpdateChecker class.
This commit is contained in:
parent
ba7fa5aea5
commit
961f92b7e2
@ -28,6 +28,8 @@
|
|||||||
#include <QThread>
|
#include <QThread>
|
||||||
#include <QDate>
|
#include <QDate>
|
||||||
|
|
||||||
|
class QUrl;
|
||||||
|
|
||||||
///////////////////////////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
namespace MUtils
|
namespace MUtils
|
||||||
@ -135,8 +137,10 @@ namespace MUtils
|
|||||||
bool tryContactHost(const QString &hostname, const int &timeoutMsec);
|
bool tryContactHost(const QString &hostname, const int &timeoutMsec);
|
||||||
bool parseVersionInfo(const QString &file, UpdateCheckerInfo *updateInfo);
|
bool parseVersionInfo(const QString &file, UpdateCheckerInfo *updateInfo);
|
||||||
|
|
||||||
bool getFile(const QString &url, const QString &outFile, const unsigned int maxRedir = 8U);
|
bool getFile(const QUrl &url, const QString &outFile, const unsigned int maxRedir = 8U);
|
||||||
bool checkSignature(const QString &file, const QString &signature);
|
bool checkSignature(const QString &file, const QString &signature);
|
||||||
bool tryUpdateMirror(UpdateCheckerInfo *updateInfo, const QString &url, const bool &quick);
|
bool tryUpdateMirror(UpdateCheckerInfo *updateInfo, const QString &url, const bool &quick);
|
||||||
|
|
||||||
|
bool invokeCurl(const QStringList &args, const QString &workingDir, const int timeout);
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
@ -199,7 +199,7 @@ void MUtils::UpdateChecker::checkForUpdates(void)
|
|||||||
|
|
||||||
// ----- Test Internet Connection ----- //
|
// ----- Test Internet Connection ----- //
|
||||||
|
|
||||||
log("Checking internet connection...", "");
|
log("Checking your Internet connection...", "");
|
||||||
setStatus(UpdateStatus_CheckingConnection);
|
setStatus(UpdateStatus_CheckingConnection);
|
||||||
|
|
||||||
const int networkStatus = OS::network_status();
|
const int networkStatus = OS::network_status();
|
||||||
@ -211,6 +211,7 @@ void MUtils::UpdateChecker::checkForUpdates(void)
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
msleep(500);
|
||||||
setProgress(1);
|
setProgress(1);
|
||||||
|
|
||||||
// ----- Test Known Hosts Connectivity ----- //
|
// ----- Test Known Hosts Connectivity ----- //
|
||||||
@ -256,7 +257,7 @@ endLoop:
|
|||||||
|
|
||||||
// ----- Fetch Update Info From Server ----- //
|
// ----- Fetch Update Info From Server ----- //
|
||||||
|
|
||||||
log("----", "", "Checking for updates online...");
|
log("----", "", "Internet connection is operational, checking for updates online...");
|
||||||
setStatus(UpdateStatus_FetchingUpdates);
|
setStatus(UpdateStatus_FetchingUpdates);
|
||||||
|
|
||||||
int mirrorCount = 0;
|
int mirrorCount = 0;
|
||||||
@ -407,7 +408,7 @@ bool MUtils::UpdateChecker::tryUpdateMirror(UpdateCheckerInfo *updateInfo, const
|
|||||||
|
|
||||||
if (quick)
|
if (quick)
|
||||||
{
|
{
|
||||||
if (!tryContactHost(QUrl(url).host(), (MAX_CONN_TIMEOUT / 10)))
|
if (!tryContactHost(QUrl(url).host(), (MAX_CONN_TIMEOUT / 8)))
|
||||||
{
|
{
|
||||||
log("", "Mirror is too slow, skipping!");
|
log("", "Mirror is too slow, skipping!");
|
||||||
return false;
|
return false;
|
||||||
@ -420,15 +421,15 @@ bool MUtils::UpdateChecker::tryUpdateMirror(UpdateCheckerInfo *updateInfo, const
|
|||||||
|
|
||||||
if (getUpdateInfo(url, outFileVers, outFileSign))
|
if (getUpdateInfo(url, outFileVers, outFileSign))
|
||||||
{
|
{
|
||||||
log("", "Download okay, checking signature:");
|
log("Download completed, verifying signature:", "");
|
||||||
if (checkSignature(outFileVers, outFileSign))
|
if (checkSignature(outFileVers, outFileSign))
|
||||||
{
|
{
|
||||||
log("", "Signature okay, parsing info:", "");
|
log("", "Signature is valid, parsing info:", "");
|
||||||
success = parseVersionInfo(outFileVers, updateInfo);
|
success = parseVersionInfo(outFileVers, updateInfo);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
log("", "Bad signature, take care!");
|
log("", "Bad signature, take care !!!");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
@ -445,12 +446,12 @@ bool MUtils::UpdateChecker::tryUpdateMirror(UpdateCheckerInfo *updateInfo, const
|
|||||||
bool MUtils::UpdateChecker::getUpdateInfo(const QString &url, const QString &outFileVers, const QString &outFileSign)
|
bool MUtils::UpdateChecker::getUpdateInfo(const QString &url, const QString &outFileVers, const QString &outFileSign)
|
||||||
{
|
{
|
||||||
log("Downloading update info:", "");
|
log("Downloading update info:", "");
|
||||||
if(getFile(QString("%1%2").arg(url, mirror_url_postfix[m_betaUpdates ? 1 : 0]), outFileVers))
|
if(getFile(QUrl(QString("%1%2").arg(url, mirror_url_postfix[m_betaUpdates ? 1 : 0])), outFileVers))
|
||||||
{
|
{
|
||||||
if (!m_cancelled)
|
if (!m_cancelled)
|
||||||
{
|
{
|
||||||
log("", "Downloading signature:", "");
|
log( "Downloading signature file:", "");
|
||||||
if (getFile(QString("%1%2.sig2").arg(url, mirror_url_postfix[m_betaUpdates ? 1 : 0]), outFileSign))
|
if (getFile(QUrl(QString("%1%2.sig2").arg(url, mirror_url_postfix[m_betaUpdates ? 1 : 0])), outFileSign))
|
||||||
{
|
{
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@ -566,7 +567,7 @@ bool MUtils::UpdateChecker::parseVersionInfo(const QString &file, UpdateCheckerI
|
|||||||
// EXTERNAL TOOLS
|
// EXTERNAL TOOLS
|
||||||
//----------------------------------------------------------
|
//----------------------------------------------------------
|
||||||
|
|
||||||
bool MUtils::UpdateChecker::getFile(const QString &url, const QString &outFile, const unsigned int maxRedir)
|
bool MUtils::UpdateChecker::getFile(const QUrl &url, const QString &outFile, const unsigned int maxRedir)
|
||||||
{
|
{
|
||||||
QFileInfo output(outFile);
|
QFileInfo output(outFile);
|
||||||
output.setCaching(false);
|
output.setCaching(false);
|
||||||
@ -576,77 +577,38 @@ bool MUtils::UpdateChecker::getFile(const QString &url, const QString &outFile,
|
|||||||
QFile::remove(output.canonicalFilePath());
|
QFile::remove(output.canonicalFilePath());
|
||||||
if (output.exists())
|
if (output.exists())
|
||||||
{
|
{
|
||||||
|
qWarning("Existing output file could not be found!");
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
QProcess process;
|
QStringList args(QLatin1String("-vsSNqkfL"));
|
||||||
init_process(process, output.absolutePath(), true, NULL, m_environment.data());
|
|
||||||
|
|
||||||
QStringList args(QLatin1String("-vsSqkfL"));
|
|
||||||
args << "-m" << QString::number(DOWNLOAD_TIMEOUT / 1000);
|
args << "-m" << QString::number(DOWNLOAD_TIMEOUT / 1000);
|
||||||
args << "--max-redirs" << QString::number(maxRedir);
|
args << "--max-redirs" << QString::number(maxRedir);
|
||||||
args << "-U" << USER_AGENT_STR;
|
args << "-A" << USER_AGENT_STR;
|
||||||
args << "-o" << output.fileName() << url;
|
args << "-e" << QString("%1://%2/;auto").arg(url.scheme(), url.host());
|
||||||
|
args << "-o" << output.fileName() << url.toString();
|
||||||
|
|
||||||
QEventLoop loop;
|
return invokeCurl(args, output.absolutePath(), DOWNLOAD_TIMEOUT);
|
||||||
connect(&process, SIGNAL(error(QProcess::ProcessError)), &loop, SLOT(quit()));
|
|
||||||
connect(&process, SIGNAL(finished(int, QProcess::ExitStatus)), &loop, SLOT(quit()));
|
|
||||||
connect(&process, SIGNAL(readyRead()), &loop, SLOT(quit()));
|
|
||||||
|
|
||||||
QTimer timer;
|
|
||||||
timer.setSingleShot(true);
|
|
||||||
connect(&timer, SIGNAL(timeout()), &loop, SLOT(quit()));
|
|
||||||
|
|
||||||
process.start(m_binaryCurl, args);
|
|
||||||
if (!process.waitForStarted())
|
|
||||||
{
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
timer.start(2 * DOWNLOAD_TIMEOUT);
|
|
||||||
|
|
||||||
while (process.state() != QProcess::NotRunning)
|
|
||||||
{
|
|
||||||
loop.exec();
|
|
||||||
const bool bTimeOut = (!timer.isActive());
|
|
||||||
while (process.canReadLine())
|
|
||||||
{
|
|
||||||
const QString line = QString::fromLatin1(process.readLine()).simplified();
|
|
||||||
if (!line.isEmpty())
|
|
||||||
{
|
|
||||||
log(line);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (bTimeOut || MUTILS_BOOLIFY(m_cancelled))
|
|
||||||
{
|
|
||||||
qWarning("cURL process timed out <-- killing!");
|
|
||||||
process.kill();
|
|
||||||
process.waitForFinished();
|
|
||||||
log(bTimeOut ? "PROCESS TIMEOUT !!!" : "CANCELLED BY USER !!!", "");
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
timer.stop();
|
|
||||||
timer.disconnect(&timer, SIGNAL(timeout()), &loop, SLOT(quit()));
|
|
||||||
|
|
||||||
log(QString().sprintf("Exited with code %d", process.exitCode()));
|
|
||||||
return (process.exitCode() == 0) && output.exists() && output.isFile();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool MUtils::UpdateChecker::tryContactHost(const QString &hostname, const int &timeoutMsec)
|
bool MUtils::UpdateChecker::tryContactHost(const QString &hostname, const int &timeoutMsec)
|
||||||
{
|
{
|
||||||
log(QString("Connecting to host: %1").arg(hostname), "");
|
log(QString("Connecting to host: %1").arg(hostname), "");
|
||||||
|
|
||||||
QProcess process;
|
QStringList args(QLatin1String("-vsSNqkI"));
|
||||||
init_process(process, temp_folder(), true, NULL, m_environment.data());
|
args << "-m" << QString::number(qMax(1, timeoutMsec / 1000));
|
||||||
|
args << "-A" << USER_AGENT_STR;
|
||||||
QStringList args(QLatin1String("-vsSqkI"));
|
|
||||||
args << "-m" << QString::number(qMax(timeoutMsec, 1000) / 1000);
|
|
||||||
args << "-U" << USER_AGENT_STR;
|
|
||||||
args << "-o" << OS::null_device() << QString("http://%1/").arg(hostname);
|
args << "-o" << OS::null_device() << QString("http://%1/").arg(hostname);
|
||||||
|
|
||||||
|
return invokeCurl(args, temp_folder(), timeoutMsec);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool MUtils::UpdateChecker::invokeCurl(const QStringList &args, const QString &workingDir, const int timeout)
|
||||||
|
{
|
||||||
|
QProcess process;
|
||||||
|
init_process(process, workingDir, true, NULL, m_environment.data());
|
||||||
|
|
||||||
QEventLoop loop;
|
QEventLoop loop;
|
||||||
connect(&process, SIGNAL(error(QProcess::ProcessError)), &loop, SLOT(quit()));
|
connect(&process, SIGNAL(error(QProcess::ProcessError)), &loop, SLOT(quit()));
|
||||||
connect(&process, SIGNAL(finished(int, QProcess::ExitStatus)), &loop, SLOT(quit()));
|
connect(&process, SIGNAL(finished(int, QProcess::ExitStatus)), &loop, SLOT(quit()));
|
||||||
@ -662,40 +624,51 @@ bool MUtils::UpdateChecker::tryContactHost(const QString &hostname, const int &t
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
timer.start(2 * qMax(timeoutMsec, 1000));
|
bool bAborted = false;
|
||||||
|
timer.start(qMax(2 * timeout, 2500));
|
||||||
|
|
||||||
while (process.state() != QProcess::NotRunning)
|
while (process.state() != QProcess::NotRunning)
|
||||||
{
|
{
|
||||||
loop.exec();
|
loop.exec();
|
||||||
const bool bTimeOut = (!timer.isActive());
|
|
||||||
while (process.canReadLine())
|
while (process.canReadLine())
|
||||||
{
|
{
|
||||||
const QString line = QString::fromLatin1(process.readLine()).simplified();
|
const QString line = QString::fromLatin1(process.readLine()).simplified();
|
||||||
if (!line.isEmpty())
|
if ((!line.isEmpty()) && line.compare(QLatin1String("<")) && line.compare(QLatin1String(">")))
|
||||||
{
|
{
|
||||||
log(line);
|
log(line);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (bTimeOut || MUTILS_BOOLIFY(m_cancelled))
|
const bool bCancelled = MUTILS_BOOLIFY(m_cancelled);
|
||||||
|
if (bAborted = (bCancelled || ((!timer.isActive()) && (!process.waitForFinished(15)))))
|
||||||
{
|
{
|
||||||
qWarning("cURL process timed out <-- killing!");
|
log(bCancelled ? "CANCELLED BY USER !!!" : "PROCESS TIMEOUT !!!", "");
|
||||||
process.kill();
|
qWarning("WARNING: cURL process %s!", bCancelled ? "cancelled" : "timed out");
|
||||||
process.waitForFinished();
|
break; /*abort process*/
|
||||||
log(bTimeOut ? "PROCESS TIMEOUT !!!" : "CANCELLED BY USER !!!", "");
|
|
||||||
return false;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
timer.stop();
|
timer.stop();
|
||||||
timer.disconnect(&timer, SIGNAL(timeout()), &loop, SLOT(quit()));
|
timer.disconnect(&timer, SIGNAL(timeout()), &loop, SLOT(quit()));
|
||||||
|
|
||||||
if (process.exitCode() != 0)
|
if (bAborted)
|
||||||
{
|
{
|
||||||
log("Connection has failed!");
|
process.kill();
|
||||||
|
process.waitForFinished(-1);
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
log(QString().sprintf("Exited with code %d", process.exitCode()), "");
|
const int exitCode = process.exitCode();
|
||||||
return (process.exitCode() == 0);
|
switch (exitCode)
|
||||||
|
{
|
||||||
|
case 0: log(QLatin1String("DONE: Transfer completed successfully."), ""); break;
|
||||||
|
case 6: log(QLatin1String("ERROR: Remote host could not be resolved!"), ""); break;
|
||||||
|
case 7: log(QLatin1String("ERROR: Connection to remote host could not be established!"), ""); break;
|
||||||
|
case 22: log(QLatin1String("ERROR: Requested URL was not found or returned an error!"), ""); break;
|
||||||
|
case 28: log(QLatin1String("ERROR: Operation timed out !!!"), ""); break;
|
||||||
|
default: log(QString().sprintf("ERROR: Terminated with unknown code %d", exitCode), ""); break;
|
||||||
|
}
|
||||||
|
|
||||||
|
return (exitCode == 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool MUtils::UpdateChecker::checkSignature(const QString &file, const QString &signature)
|
bool MUtils::UpdateChecker::checkSignature(const QString &file, const QString &signature)
|
||||||
|
Loading…
Reference in New Issue
Block a user