diff options
Diffstat (limited to 'core/checkcloudconnection.cpp')
-rw-r--r-- | core/checkcloudconnection.cpp | 77 |
1 files changed, 77 insertions, 0 deletions
diff --git a/core/checkcloudconnection.cpp b/core/checkcloudconnection.cpp index b9a7d3b0e..714b62836 100644 --- a/core/checkcloudconnection.cpp +++ b/core/checkcloudconnection.cpp @@ -4,11 +4,14 @@ #include <QNetworkAccessManager> #include <QNetworkReply> #include <QEventLoop> +#include <QHostAddress> #include "pref.h" #include "qthelper.h" #include "git-access.h" #include "errorhelper.h" +#include "core/subsurface-string.h" +#include "core/settings/qPrefCloudStorage.h" #include "checkcloudconnection.h" @@ -19,6 +22,10 @@ CheckCloudConnection::CheckCloudConnection(QObject *parent) : } +// two free APIs to figure out where we are +#define GET_EXTERNAL_IP_API "http://api.ipify.org" +#define GET_CONTINENT_API "http://ip-api.com/line/%1?fields=continent" + // our own madeup API to make sure we are talking to a Subsurface cloud server #define TEAPOT "/make-latte?number-of-shots=3" #define HTTP_I_AM_A_TEAPOT 418 @@ -84,6 +91,76 @@ void CheckCloudConnection::sslErrors(const QList<QSslError> &errorList) qDebug() << err.errorString(); } +void CheckCloudConnection::pickServer() +{ + QNetworkRequest request(QString(GET_EXTERNAL_IP_API)); + request.setRawHeader("Accept", "text/plain"); + request.setRawHeader("User-Agent", getUserAgent().toUtf8()); + QNetworkAccessManager *mgr = new QNetworkAccessManager(); + connect(mgr, &QNetworkAccessManager::finished, this, &CheckCloudConnection::gotIP); + mgr->get(request); +} + +void CheckCloudConnection::gotIP(QNetworkReply *reply) +{ + if (reply->error() != QNetworkReply::NoError) { + // whatever, just use the default host + if (verbose) + qDebug() << __FUNCTION__ << "got error reply from ip webservice - not changing cloud host"; + return; + } + QString addressString = reply->readAll(); + // use the QHostAddress constructor as a convenient way to validate that this is indeed an IP address + // but then don't do annything with the QHostAdress - we need the address string... + QHostAddress addr(addressString); + if (addr.isNull()) { + // this isn't an address, don't try to update the cloud host + if (verbose) + qDebug() << __FUNCTION__ << "returned address doesn't appear to be valid (" << addressString << ") - not changing cloud host"; + return; + } + if (verbose) + qDebug() << "IP used for cloud server access" << addressString; + // now figure out which continent we are on + QNetworkRequest request(QString(GET_CONTINENT_API).arg(addressString)); + request.setRawHeader("Accept", "text/plain"); + request.setRawHeader("User-Agent", getUserAgent().toUtf8()); + QNetworkAccessManager *mgr = new QNetworkAccessManager(); + connect(mgr, &QNetworkAccessManager::finished, this, &CheckCloudConnection::gotContinent); + mgr->get(request); +} + +void CheckCloudConnection::gotContinent(QNetworkReply *reply) +{ + if (reply->error() != QNetworkReply::NoError) { + // whatever, just use the default host + if (verbose) + qDebug() << __FUNCTION__ << "got error reply from ip location webservice - not changing cloud host"; + return; + } + QString continentString = reply->readAll(); + // in most cases this response comes back too late for us - we may already have + // started to talk to the cloud server (this certinaly seems to be the case when + // we use the cloud storage as default file). So instead of potentially changing + // the server that is used in mid connection, let's just update what's stored in + // our settings so the next time we'll use the server that's closer. + + // of course, right now the logic for that is very simplistic. Use the US server + // when in the Americas, the EU server otherwise. This may need a better algorithm + // at some point, but for now it seems good enough + + const char *base_url; + if (continentString.contains("America", Qt::CaseInsensitive)) + base_url = "https://" CLOUD_HOST_US "/"; + else + base_url = "https://" CLOUD_HOST_EU "/"; + if (!same_string(base_url, prefs.cloud_base_url)) { + if (verbose) + qDebug() << "remember cloud server" << base_url << "based on IP location in " << continentString; + qPrefCloudStorage::instance()->store_cloud_base_url(base_url); + } +} + // helper to be used from C code extern "C" bool canReachCloudServer() { |