Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
25 changes: 19 additions & 6 deletions News.qml
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,11 @@ Item {
bottomMargin: 10
}

function fetchFallbackNews() {
console.log("fetching fallback posts json");
fetchNews(downloader.newsFallbackUrl);
}

function fetchNews(jsonUrl) {
var news = new XMLHttpRequest();

Expand All @@ -55,11 +60,8 @@ Item {
}

if (newsObj === null) {
var fallbackJsonUrl = 'qrc:/resources/disconnected_posts.json';

if (jsonUrl !== fallbackJsonUrl) {
console.log("fetching fallback posts json");
fetchNews(fallbackJsonUrl);
if (jsonUrl !== downloader.newsFallbackUrl) {
fetchFallbackNews();
return;
}
}
Expand Down Expand Up @@ -98,6 +100,14 @@ Item {
news.send();
}

Connections {
target: splashController

onNewsUrlFetched: {
fetchNews(newsUrl);
}
}

SwipeView {
id: swipe

Expand All @@ -111,7 +121,10 @@ Item {
}

Component.onCompleted: {
fetchNews('https://unvanquished.net/api/get_recent_posts/');
var newsUrl = downloader.newsUrl;
if (newsUrl != "") {
fetchNews(newsUrl);
}
}
}

Expand Down
2 changes: 1 addition & 1 deletion ariadownloader.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -65,7 +65,7 @@ AriaDownloader::AriaDownloader(const std::string& ariaLogFilename) : callback_(n
AriaDownloader::~AriaDownloader()
{
aria2::sessionFinal(session_);
aria2::libraryDeinit();
// aria2::libraryDeinit();
}

bool AriaDownloader::addUri(const std::string& uri)
Expand Down
137 changes: 120 additions & 17 deletions currentversionfetcher.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -16,54 +16,157 @@
*/

#include "currentversionfetcher.h"
#include "system.h"

#include <QDebug>
#include <QUrl>
#include <QNetworkRequest>
#include <QNetworkReply>
#include <QJsonDocument>
#include <QJsonObject>
#include <QJsonArray>

CurrentVersionFetcher::CurrentVersionFetcher(QObject* parent) : QObject(parent), manager_(new QNetworkAccessManager(this))
{
connect(manager_.get(), SIGNAL(finished(QNetworkReply*)), this, SLOT(reply(QNetworkReply*)));
}

void CurrentVersionFetcher::fetchCurrentVersion(QString url)
static const QString versionMirrors[] = {
"https://cdn.unvanquished.net/",
"https://cdn.illwieckz.net/unvanquished/",
"https://webseed.unv.kangz.net/",
nullptr,
};

static const QString *versionMirror = &versionMirrors[0];

void CurrentVersionFetcher::fetchCurrentVersion()
{
static const QString versionFile = "current.json";

if (versionMirror) {
QString versionURL = versionMirror + versionFile;
qDebug() << "Fetching" << versionURL;
QNetworkRequest request = QNetworkRequest(QUrl(versionURL));
manager_->get(request);
versionMirror++;
}
}

void ComponentVersionFetcher(QJsonObject components, QString name, QString system, QString *version, QStringList *urls)
{
QNetworkRequest request = QNetworkRequest(QUrl(url));
manager_->get(request);
QString path;
QJsonArray mirrors;

QJsonObject component = components[name].toObject();

if (component.isEmpty()) {
qDebug() << "ComponentVersionFetcher: undefined “" << name << "” key";
} else {
QJsonValue versionValue = component.value("version");
if (versionValue == QJsonValue::Undefined) {
qDebug() << "ComponentVersionFetcher: undefined “version” value for" << name;
} else {
*version = versionValue.toString();
}

mirrors = component["mirrors"].toArray();
if (!mirrors.count()) {
qDebug() << "ComponentVersionFetcher: undefined “mirrors” key for " << name;
}

QJsonObject parcels = component["parcels"].toObject();
if (parcels.isEmpty()) {
qDebug() << "ComponentVersionFetcher: undefined “parcels” key for" << name;
} else {
QJsonObject systemObject = parcels[system].toObject();
if (systemObject.isEmpty()) {
qDebug() << "ComponentVersionFetcher: undefined “" << system << "” key for " << name;
} else {
QJsonValue pathValue = systemObject.value("path");
if (pathValue == QJsonValue::Undefined) {
qDebug() << "ComponentVersionFetcher: undefined “path” value for" << name;
} else {
path = pathValue.toString();
}
}
}
}

qDebug() << "ComponentVersionFetcher: fetched component =" << name;
qDebug() << "ComponentVersionFetcher: fetched system =" << system;
qDebug() << "ComponentVersionFetcher: fetched version =" << *version;
qDebug() << "ComponentVersionFetcher: fetched path =" << path;

for (auto m : mirrors)
{
QString mirror = m.toString();
qDebug() << "ComponentVersionFetcher: fetched mirror =" << mirror;
QString url = mirror + path;
qDebug() << "ComponentVersionFetcher: fetched url =" << url;
urls->append(url);
}
}

void CurrentVersionFetcher::reply(QNetworkReply* reply)
{
QString game;
QString updater;
QString formatVersion;
QString updaterVersion;
QStringList updaterUrls;
QString gameVersion;
QStringList gameUrls;
QString newsVersion;
QStringList newsUrls;

if (reply->error() != QNetworkReply::NoError) {
qDebug() << "CurrentVersionFetcher: network error";
emit onCurrentVersions(updater, game);

if (versionMirror) {
fetchCurrentVersion();
} else {
emit onCurrentVersions(updaterVersion, updaterUrls, gameVersion, gameUrls, "");
}
return;
}

QJsonParseError error;
QJsonDocument json = QJsonDocument::fromJson(reply->readAll(), &error);
if (error.error != QJsonParseError::NoError) {
qDebug() << "CurrentVersionFetcher: JSON parsing error";
emit onCurrentVersions(updater, game);
emit onCurrentVersions(updaterVersion, updaterUrls, gameVersion, gameUrls, "");
return;
}
QJsonValue value = json.object().value("updater");
if (value != QJsonValue::Undefined) {
updater = value.toString();

QJsonObject jsonObject = json.object();

QJsonValue formatVersionValue = jsonObject.value("format");

if (formatVersionValue == QJsonValue::Undefined) {
qDebug() << "ComponentVersionFetcher: missing “version” value in current.json";
emit onCurrentVersions(updaterVersion, updaterUrls, gameVersion, gameUrls, "");
return;
} else {
qDebug() << "CurrentVersionFetcher: undefined “updater” value";
formatVersion = formatVersionValue.toString();
}
value = json.object().value("unvanquished");
if (value != QJsonValue::Undefined) {
game = value.toString();

QJsonValue componentsValue = jsonObject.value("components");

if (componentsValue == QJsonValue::Undefined) {
qDebug() << "ComponentVersionFetcher: missing “components” array in current.json";
emit onCurrentVersions(updaterVersion, updaterUrls, gameVersion, gameUrls, "");
return;
} else {
qDebug() << "CurrentVersionFetcher: undefined “unvanquished” value";
qDebug() << "ComponentVersionFetcher: fetched format = " << formatVersion;

QJsonObject components = componentsValue.toObject();

ComponentVersionFetcher(components, "updater", Sys::updaterSystem(), &updaterVersion, &updaterUrls);

ComponentVersionFetcher(components, "game", "all-all", &gameVersion, &gameUrls);

ComponentVersionFetcher(components, "news", "all-all", &newsVersion, &newsUrls);
}
qDebug() << "CurrentVersionFetcher: fetched versions: updater =" << updater << "game =" << game;
emit onCurrentVersions(updater, game);

emit onCurrentVersions(updaterVersion, updaterUrls, gameVersion, gameUrls, newsUrls.at(0));
}

4 changes: 2 additions & 2 deletions currentversionfetcher.h
Original file line number Diff line number Diff line change
Expand Up @@ -28,10 +28,10 @@ class CurrentVersionFetcher : public QObject
Q_OBJECT
public:
explicit CurrentVersionFetcher(QObject *parent = nullptr);
void fetchCurrentVersion(QString url);
void fetchCurrentVersion();

signals:
void onCurrentVersions(QString updater, QString game);
void onCurrentVersions(QString updaterVersion, QStringList updaterUrls, QString gameVersion, QStringList gameUrls, QString newsUrl);

private slots:
void reply(QNetworkReply* reply);
Expand Down
4 changes: 2 additions & 2 deletions deployment.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
## Network resources used by the updater
- News REST endpoint which returns links to Wordpress articles on unvanquished.net. The featured image in each news article must be a type which is supported by the updater (see issue #51). Currently PNG and JPEG are known to work.
- versions.json file on unvanquished.net, used to determine whether update is needed
- current.json file on unvanquished.net, used to determine whether update is needed
- Github releases. These are targeted by download links on unvanquished.net and by the updater's self-update process.
- Torrent URL used to download the latest game version

Expand Down Expand Up @@ -36,4 +36,4 @@
```
2. Upload `UnvUpdaterWin.zip` and `UnvanquishedUpdater.exe` from `build-docker/release-win/`.

4. Bump the updater version on unvanquished.net to the new tag, so that it is reflected in versions.json and the download links.
4. Bump the updater version on unvanquished.net to the new tag, so that it is reflected in current.json and the download links.
2 changes: 0 additions & 2 deletions downloadworker.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -143,8 +143,6 @@ std::string DownloadWorker::getAriaIndexOut(size_t index, std::string path)
return std::to_string(index) + "=" + oldPath.toStdString();
}



void DownloadWorker::download()
{
auto start = std::chrono::steady_clock::now();
Expand Down
2 changes: 1 addition & 1 deletion gamelauncher.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ GameLauncher::GameLauncher(const QString& connectUrl, const Settings& settings)
// Does our version of daemon have -connect-trusted?
static bool haveConnectTrusted(const QString& gameVersion)
{
// Updater version up to v0.2.0 may set "unknown" as game version if versions.json request fails
// Updater version up to v0.2.0 may set "unknown" as game version if current.json request fails
if (gameVersion == "unknown")
return false;
// Hacky string comparison, assume we won't go down to 0.9 or up to 0.100 :)
Expand Down
10 changes: 5 additions & 5 deletions linux.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -82,6 +82,11 @@ QString archiveName()
return "linux-amd64.zip";
}

QString updaterSystem()
{
return "linux-amd64";
}

void migrateHomePath()
{
QString legacyHomePath = QDir::homePath() + "/.unvanquished";
Expand Down Expand Up @@ -265,11 +270,6 @@ bool updateUpdater(const QString& updaterArchive, const QString& connectUrl)
return false;
}

QString updaterArchiveName()
{
return "UnvUpdaterLinux.zip";
}

std::string getCertStore()
{
// From Go: https://golang.org/src/crypto/x509/root_linux.go
Expand Down
17 changes: 12 additions & 5 deletions main.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -63,7 +63,7 @@ struct CommandLineOptions {
QString ariaLogFilename;
int splashMilliseconds = 3000;
RelaunchCommand relaunchCommand = RelaunchCommand::NONE;
QString updateUpdaterVersion;
QStringList updateUpdaterUrls;
QString connectUrl;
};

Expand Down Expand Up @@ -122,13 +122,16 @@ CommandLineOptions getCommandLineOptions(const QApplication& app) {
splashMsOption.setValueName("duration in milliseconds");
QCommandLineOption internalCommandOption("internalcommand");
internalCommandOption.setValueName("command");
QCommandLineOption updaterUrl("updaterurl");
updaterUrl.setValueName("url");
QCommandLineParser optionParser;
optionParser.addHelpOption();
optionParser.addVersionOption();
optionParser.addOption(logFileNameOption);
optionParser.addOption(ariaLogFilenameOption);
optionParser.addOption(splashMsOption);
optionParser.addOption(internalCommandOption);
optionParser.addOption(updaterUrl);
optionParser.addPositionalArgument("URL", "address of Unvanquished server to connect to", "[URL]");
optionParser.process(app);
CommandLineOptions options;
Expand All @@ -145,9 +148,13 @@ CommandLineOptions getCommandLineOptions(const QApplication& app) {
options.relaunchCommand = RelaunchCommand::PLAY_NOW;
} else if (command == "updategame") {
options.relaunchCommand = RelaunchCommand::UPDATE_GAME;
} else if (command.startsWith("updateupdater:")) {
} else if (command.startsWith("updateupdater")) {
options.relaunchCommand = RelaunchCommand::UPDATE_UPDATER;
options.updateUpdaterVersion = command.section(':', 1);
if (optionParser.isSet(updaterUrl)) {
options.updateUpdaterUrls = optionParser.values(updaterUrl);
} else {
options.updateUpdaterUrls = QStringList();
}
} else {
argParseError("Invalid --internalcommand option: " + command);
}
Expand Down Expand Up @@ -209,9 +216,9 @@ int main(int argc, char *argv[])
}

SplashController splashController(
options.relaunchCommand, options.updateUpdaterVersion, options.connectUrl, settings);
options.relaunchCommand, options.updateUpdaterUrls, options.connectUrl, settings);
splashController.checkForUpdate();
QmlDownloader downloader(options.ariaLogFilename, options.connectUrl, settings);
QmlDownloader downloader(options.ariaLogFilename, options.connectUrl, splashController, settings);
QQmlApplicationEngine engine;
engine.addImportPath(QLatin1String("qrc:/"));
engine.addImageProvider(QLatin1String("fluidicons"), new IconsImageProvider());
Expand Down
10 changes: 5 additions & 5 deletions osx.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,11 @@ QString archiveName()
return "macos-amd64.zip";
}

QString updaterSystem()
{
return "macos-amd64";
}

QString defaultInstallPath()
{
return QDir::homePath() + "/Games/Unvanquished";
Expand Down Expand Up @@ -163,11 +168,6 @@ bool updateUpdater(const QString& updaterArchive, const QString&)
return true;
}

QString updaterArchiveName()
{
return "UnvUpdaterOSX.zip";
}

std::string getCertStore()
{
return ""; // Not used on OSX.
Expand Down
Loading