aboutsummaryrefslogtreecommitdiffstats
path: root/core/checkcloudconnection.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'core/checkcloudconnection.cpp')
-rw-r--r--core/checkcloudconnection.cpp77
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()
{