ssl: Use QSslSocket directly to avoid redundant qobject_casts
[quassel.git] / src / core / core.cpp
index 1ff4ada..11563fd 100644 (file)
@@ -1,5 +1,5 @@
 /***************************************************************************
- *   Copyright (C) 2005-2018 by the Quassel Project                        *
+ *   Copyright (C) 2005-2020 by the Quassel Project                        *
  *   devel@quassel-irc.org                                                 *
  *                                                                         *
  *   This program is free software; you can redistribute it and/or modify  *
  *   51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.         *
  ***************************************************************************/
 
+#include "core.h"
+
 #include <algorithm>
 
 #include <QCoreApplication>
 
-#include "core.h"
 #include "coreauthhandler.h"
 #include "coresession.h"
 #include "coresettings.h"
-#include "logger.h"
 #include "internalpeer.h"
 #include "network.h"
 #include "postgresqlstorage.h"
 #include "quassel.h"
 #include "sqlauthenticator.h"
 #include "sqlitestorage.h"
+#include "types.h"
 #include "util.h"
 
-// Currently building with LDAP bindings is optional.
 #ifdef HAVE_LDAP
-#include "ldapauthenticator.h"
+#    include "ldapauthenticator.h"
 #endif
 
 // migration related
 #include <QFile>
 #ifdef Q_OS_WIN
-#  include <windows.h>
+#    include <windows.h>
 #else
-#  include <unistd.h>
-#  include <termios.h>
+#    include <termios.h>
+#    include <unistd.h>
 #endif /* Q_OS_WIN */
 
 // ==============================
@@ -57,30 +57,23 @@ const int Core::AddClientEventId = QEvent::registerEventType();
 class AddClientEvent : public QEvent
 {
 public:
-    AddClientEvent(RemotePeer *p, UserId uid) : QEvent(QEvent::Type(Core::AddClientEventId)), peer(p), userId(uid) {}
-    RemotePeer *peer;
+    AddClientEvent(RemotePeer* p, UserId uid)
+        : QEvent(QEvent::Type(Core::AddClientEventId))
+        , peer(p)
+        , userId(uid)
+    {}
+    RemotePeer* peer;
     UserId userId;
 };
 
-
 // ==============================
 //  Core
 // ==============================
-Core *Core::_instance{nullptr};
-
-Core *Core::instance()
-{
-    return _instance;
-}
-
 
 Core::Core()
+    : Singleton<Core>{this}
 {
-    if (_instance) {
-        qWarning() << "Recreating core instance!";
-        delete _instance;
-    }
-    _instance = this;
+    Q_INIT_RESOURCE(sql);
 
     // Parent all QObject-derived attributes, so when the Core instance gets moved into another
     // thread, they get moved with it
@@ -89,32 +82,22 @@ Core::Core()
     _storageSyncTimer.setParent(this);
 }
 
-
 Core::~Core()
 {
-    saveState();
     qDeleteAll(_connectingClients);
     qDeleteAll(_sessions);
     syncStorage();
-    _instance = nullptr;
 }
 
-
-bool Core::init()
+void Core::init()
 {
-    _startTime = QDateTime::currentDateTime().toUTC(); // for uptime :)
-
-    if (Quassel::runMode() == Quassel::RunMode::CoreOnly) {
-        Quassel::loadTranslation(QLocale::system());
-    }
+    _startTime = QDateTime::currentDateTime().toUTC();  // for uptime :)
 
     // check settings version
     // so far, we only have 1
     CoreSettings s;
     if (s.version() != 1) {
-        qCritical() << "Invalid core settings version, terminating!";
-        QCoreApplication::exit(EXIT_FAILURE);
-        return false;
+        throw ExitException{EXIT_FAILURE, tr("Invalid core settings version!")};
     }
 
     // Set up storage and authentication backends
@@ -135,7 +118,8 @@ bool Core::init()
     if (config_from_environment) {
         db_backend = environment.value("DB_BACKEND");
         auth_authenticator = environment.value("AUTH_AUTHENTICATOR");
-    } else {
+    }
+    else {
         CoreSettings cs;
 
         QVariantMap dbsettings = cs.storageSettings().toMap();
@@ -149,12 +133,15 @@ bool Core::init()
         writeError = !cs.isWritable();
     }
 
-    // legacy
-    _configured = initStorage(db_backend, db_connectionProperties, environment, config_from_environment);
-
-    // Not entirely sure what is 'legacy' about the above, but it seems to be the way things work!
-    if (_configured) {
-        initAuthenticator(auth_authenticator, auth_properties, environment, config_from_environment);
+    try {
+        _configured = initStorage(db_backend, db_connectionProperties, environment, config_from_environment);
+        if (_configured) {
+            _configured = initAuthenticator(auth_authenticator, auth_properties, environment, config_from_environment);
+        }
+    }
+    catch (ExitException) {
+        // Try again later
+        _configured = false;
     }
 
     if (Quassel::isOptionSet("select-backend") || Quassel::isOptionSet("select-authenticator")) {
@@ -165,52 +152,52 @@ bool Core::init()
         if (Quassel::isOptionSet("select-authenticator")) {
             success &= selectAuthenticator(Quassel::optionValue("select-authenticator"));
         }
-        QCoreApplication::exit(success ? EXIT_SUCCESS : EXIT_FAILURE);
-        return success;
+        throw ExitException{success ? EXIT_SUCCESS : EXIT_FAILURE};
     }
 
     if (!_configured) {
         if (config_from_environment) {
-            _configured = initStorage(db_backend, db_connectionProperties, environment, config_from_environment, true);
-            initAuthenticator(auth_authenticator, auth_properties, environment, config_from_environment, true);
+            try {
+                _configured = initStorage(db_backend, db_connectionProperties, environment, config_from_environment, true);
+                if (_configured) {
+                    _configured = initAuthenticator(auth_authenticator, auth_properties, environment, config_from_environment, true);
+                }
+            }
+            catch (ExitException e) {
+                throw ExitException{EXIT_FAILURE, tr("Cannot configure from environment: %1").arg(e.errorString)};
+            }
 
             if (!_configured) {
-                qWarning() << "Cannot configure from environment";
-                QCoreApplication::exit(EXIT_FAILURE);
-                return false;
+                throw ExitException{EXIT_FAILURE, tr("Cannot configure from environment!")};
             }
         }
         else {
             if (_registeredStorageBackends.empty()) {
-                quWarning() << qPrintable(tr("Could not initialize any storage backend! Exiting..."));
-                quWarning()
-                        << qPrintable(tr("Currently, Quassel supports SQLite3 and PostgreSQL. You need to build your\n"
-                                         "Qt library with the sqlite or postgres plugin enabled in order for quasselcore\n"
-                                         "to work."));
-                QCoreApplication::exit(EXIT_FAILURE); // TODO make this less brutal (especially for mono client -> popup)
-                return false;
+                throw ExitException{EXIT_FAILURE,
+                                    tr("Could not initialize any storage backend! Exiting...\n"
+                                       "Currently, Quassel supports SQLite3 and PostgreSQL. You need to build your\n"
+                                       "Qt library with the sqlite or postgres plugin enabled in order for quasselcore\n"
+                                       "to work.")};
             }
 
             if (writeError) {
-                qWarning() << "Cannot write quasselcore configuration; probably a permission problem.";
-                QCoreApplication::exit(EXIT_FAILURE);
-                return false;
+                throw ExitException{EXIT_FAILURE, tr("Cannot write quasselcore configuration; probably a permission problem.")};
             }
 
-            quInfo() << "Core is currently not configured! Please connect with a Quassel Client for basic setup.";
+            qInfo() << "Core is currently not configured! Please connect with a Quassel Client for basic setup.";
         }
     }
-    else {
+
+    // This checks separately because config-from-environment might have only configured the core just now
+    if (_configured) {
         if (Quassel::isOptionSet("add-user")) {
             bool success = createUser();
-            QCoreApplication::exit(success ? EXIT_SUCCESS : EXIT_FAILURE);
-            return success;
+            throw ExitException{success ? EXIT_SUCCESS : EXIT_FAILURE};
         }
 
         if (Quassel::isOptionSet("change-userpass")) {
             bool success = changeUserPass(Quassel::optionValue("change-userpass"));
-            QCoreApplication::exit(success ? EXIT_SUCCESS : EXIT_FAILURE);
-            return success;
+            throw ExitException{success ? EXIT_SUCCESS : EXIT_FAILURE};
         }
 
         _strictIdentEnabled = Quassel::isOptionSet("strict-ident");
@@ -221,10 +208,15 @@ bool Core::init()
         if (Quassel::isOptionSet("oidentd")) {
             _oidentdConfigGenerator = new OidentdConfigGenerator(this);
         }
-        
 
         if (Quassel::isOptionSet("ident-daemon")) {
-            _identServer = new IdentServer(_strictIdentEnabled, this);
+            _identServer = new IdentServer(this);
+        }
+
+        if (Quassel::isOptionSet("metrics-daemon")) {
+            _metricsServer = new MetricsServer(this);
+            _server.setMetricsServer(_metricsServer);
+            _v6server.setMetricsServer(_metricsServer);
         }
 
         Quassel::registerReloadHandler([]() {
@@ -237,16 +229,15 @@ bool Core::init()
             return false;
         });
 
-        connect(&_storageSyncTimer, SIGNAL(timeout()), this, SLOT(syncStorage()));
-        _storageSyncTimer.start(10 * 60 * 1000); // 10 minutes
+        connect(&_storageSyncTimer, &QTimer::timeout, this, &Core::syncStorage);
+        _storageSyncTimer.start(10 * 60 * 1000);  // 10 minutes
     }
 
-    connect(&_server, SIGNAL(newConnection()), this, SLOT(incomingConnection()));
-    connect(&_v6server, SIGNAL(newConnection()), this, SLOT(incomingConnection()));
+    connect(&_server, &QTcpServer::newConnection, this, &Core::incomingConnection);
+    connect(&_v6server, &QTcpServer::newConnection, this, &Core::incomingConnection);
 
     if (!startListening()) {
-        QCoreApplication::exit(EXIT_FAILURE);  // TODO make this less brutal
-        return false;
+        throw ExitException{EXIT_FAILURE, tr("Cannot open port for listening!")};
     }
 
     if (_configured && !Quassel::isOptionSet("norestore")) {
@@ -259,8 +250,47 @@ bool Core::init()
         connectInternalPeer(_pendingInternalConnection);
         _pendingInternalConnection = {};
     }
+}
 
-    return true;
+void Core::initAsync()
+{
+    try {
+        init();
+    }
+    catch (ExitException e) {
+        emit exitRequested(e.exitCode, e.errorString);
+    }
+}
+
+void Core::shutdown()
+{
+    qInfo() << "Core shutting down...";
+
+    saveState();
+
+    for (auto&& client : _connectingClients) {
+        client->deleteLater();
+    }
+    _connectingClients.clear();
+
+    if (_sessions.isEmpty()) {
+        emit shutdownComplete();
+        return;
+    }
+
+    for (auto&& session : _sessions) {
+        connect(session, &SessionThread::shutdownComplete, this, &Core::onSessionShutdown);
+        session->shutdown();
+    }
+}
+
+void Core::onSessionShutdown(SessionThread* session)
+{
+    _sessions.take(_sessions.key(session))->deleteLater();
+    if (_sessions.isEmpty()) {
+        qInfo() << "Core shutdown complete!";
+        emit shutdownComplete();
+    }
 }
 
 /*** Session Restore ***/
@@ -269,21 +299,20 @@ void Core::saveState()
 {
     if (_storage) {
         QVariantList activeSessions;
-        for (auto &&user : instance()->_sessions.keys())
-            activeSessions << QVariant::fromValue<UserId>(user);
+        for (auto&& user : instance()->_sessions.keys())
+            activeSessions << QVariant::fromValue(user);
         _storage->setCoreState(activeSessions);
     }
 }
 
-
 void Core::restoreState()
 {
     if (!_configured) {
-        quWarning() << qPrintable(tr("Cannot restore a state for an unconfigured core!"));
+        qWarning() << qPrintable(tr("Cannot restore a state for an unconfigured core!"));
         return;
     }
     if (_sessions.count()) {
-        quWarning() << qPrintable(tr("Calling restoreState() even though active sessions exist!"));
+        qWarning() << qPrintable(tr("Calling restoreState() even though active sessions exist!"));
         return;
     }
 
@@ -291,33 +320,41 @@ void Core::restoreState()
     /* We don't check, since we are at the first version since switching to Git
     uint statever = s.coreState().toMap()["CoreStateVersion"].toUInt();
     if(statever < 1) {
-      quWarning() << qPrintable(tr("Core state too old, ignoring..."));
+      qWarning() << qPrintable(tr("Core state too old, ignoring..."));
       return;
     }
     */
 
-    const QList<QVariant> &activeSessionsFallback = s.coreState().toMap()["ActiveSessions"].toList();
+    const QList<QVariant>activeSessionsFallback = s.coreState().toMap()["ActiveSessions"].toList();
     QVariantList activeSessions = instance()->_storage->getCoreState(activeSessionsFallback);
 
     if (activeSessions.count() > 0) {
-        quInfo() << "Restoring previous core state...";
-        for(auto &&v : activeSessions) {
+        qInfo() << "Restoring previous core state...";
+        for (auto&& v : activeSessions) {
             UserId user = v.value<UserId>();
             sessionForUser(user, true);
         }
     }
 }
 
-
 /*** Core Setup ***/
 
-QString Core::setup(const QString &adminUser, const QString &adminPassword, const QString &backend, const QVariantMap &setupData, const QString &authenticator, const QVariantMap &authSetupData)
+QString Core::setup(const QString& adminUser,
+                    const QString& adminPassword,
+                    const QString& backend,
+                    const QVariantMap& setupData,
+                    const QString& authenticator,
+                    const QVariantMap& authSetupData)
 {
     return instance()->setupCore(adminUser, adminPassword, backend, setupData, authenticator, authSetupData);
 }
 
-
-QString Core::setupCore(const QString &adminUser, const QString &adminPassword, const QString &backend, const QVariantMap &setupData, const QString &authenticator, const QVariantMap &authSetupData)
+QString Core::setupCore(const QString& adminUser,
+                        const QString& adminPassword,
+                        const QString& backend,
+                        const QVariantMap& setupData,
+                        const QString& authenticator,
+                        const QVariantMap& authSetupData)
 {
     if (_configured)
         return tr("Core is already configured! Not configuring again...");
@@ -325,14 +362,20 @@ QString Core::setupCore(const QString &adminUser, const QString &adminPassword,
     if (adminUser.isEmpty() || adminPassword.isEmpty()) {
         return tr("Admin user or password not set.");
     }
-    if (!(_configured = initStorage(backend, setupData, {}, false, true))) {
-        return tr("Could not setup storage!");
-    }
+    try {
+        if (!(_configured = initStorage(backend, setupData, {}, false, true))) {
+            return tr("Could not setup storage!");
+        }
 
-    quInfo() << "Selected authenticator:" << authenticator;
-    if (!(_configured = initAuthenticator(authenticator, authSetupData, {}, false, true)))
-    {
-        return tr("Could not setup authenticator!");
+        qInfo() << "Selected authenticator:" << authenticator;
+        if (!(_configured = initAuthenticator(authenticator, authSetupData, {}, false, true))) {
+            return tr("Could not setup authenticator!");
+        }
+    }
+    catch (ExitException e) {
+        // Event loop is running, so trigger an exit rather than throwing an exception
+        QCoreApplication::exit(e.exitCode);
+        return e.errorString.isEmpty() ? tr("Fatal failure while trying to setup, terminating") : e.errorString;
     }
 
     if (!saveBackendSettings(backend, setupData)) {
@@ -340,14 +383,13 @@ QString Core::setupCore(const QString &adminUser, const QString &adminPassword,
     }
     saveAuthenticatorSettings(authenticator, authSetupData);
 
-    quInfo() << qPrintable(tr("Creating admin user..."));
+    qInfo() << qPrintable(tr("Creating admin user..."));
     _storage->addUser(adminUser, adminPassword);
     cacheSysIdent();
-    startListening(); // TODO check when we need this
+    startListening();  // TODO check when we need this
     return QString();
 }
 
-
 QString Core::setupCoreForInternalUsage()
 {
     Q_ASSERT(!_registeredStorageBackends.empty());
@@ -363,7 +405,6 @@ QString Core::setupCoreForInternalUsage()
     return setupCore("AdminUser", QString::number(pass), "SQLite", QVariantMap(), "Database", QVariantMap());
 }
 
-
 /*** Storage Handling ***/
 
 template<typename Storage>
@@ -376,7 +417,6 @@ void Core::registerStorageBackend()
         backend->deleteLater();
 }
 
-
 void Core::registerStorageBackends()
 {
     if (_registeredStorageBackends.empty()) {
@@ -385,23 +425,19 @@ void Core::registerStorageBackends()
     }
 }
 
-
-DeferredSharedPtr<Storage> Core::storageBackend(const QString &backendId) const
+DeferredSharedPtr<Storage> Core::storageBackend(const QString& backendId) const
 {
-    auto it = std::find_if(_registeredStorageBackends.begin(), _registeredStorageBackends.end(),
-                           [backendId](const DeferredSharedPtr<Storage> &backend) {
-                               return backend->displayName() == backendId;
-                           });
+    auto it = std::find_if(_registeredStorageBackends.begin(),
+                           _registeredStorageBackends.end(),
+                           [backendId](const DeferredSharedPtr<Storage>& backend) { return backend->displayName() == backendId; });
     return it != _registeredStorageBackends.end() ? *it : nullptr;
 }
 
-// old db settings:
-// "Type" => "sqlite"
-bool Core::initStorage(const QString &backend, const QVariantMap &settings,
-                       const QProcessEnvironment &environment, bool loadFromEnvironment, bool setup)
+bool Core::initStorage(
+    const QString& backend, const QVariantMap& settings, const QProcessEnvironment& environment, bool loadFromEnvironment, bool setup)
 {
     if (backend.isEmpty()) {
-        quWarning() << "No storage backend selected!";
+        qWarning() << "No storage backend selected!";
         return false;
     }
 
@@ -411,7 +447,7 @@ bool Core::initStorage(const QString &backend, const QVariantMap &settings,
         return false;
     }
 
-    connect(storage.get(), SIGNAL(dbUpgradeInProgress(bool)), this, SIGNAL(dbUpgradeInProgress(bool)));
+    connect(storage.get(), &Storage::dbUpgradeInProgress, this, &Core::dbUpgradeInProgress);
 
     Storage::State storageState = storage->init(settings, environment, loadFromEnvironment);
     switch (storageState) {
@@ -422,35 +458,32 @@ bool Core::initStorage(const QString &backend, const QVariantMap &settings,
             return initStorage(backend, settings, environment, loadFromEnvironment, false);
         return false;
 
-    // if initialization wasn't successful, we quit to keep from coming up unconfigured
     case Storage::NotAvailable:
-        qCritical() << "FATAL: Selected storage backend is not available:" << backend;
         if (!setup) {
-            QCoreApplication::exit(EXIT_FAILURE);
+            // If initialization wasn't successful, we quit to keep from coming up unconfigured
+            throw ExitException{EXIT_FAILURE, tr("Selected storage backend %1 is not available.").arg(backend)};
         }
+        qCritical() << "Selected storage backend is not available:" << backend;
         return false;
 
     case Storage::IsReady:
         // delete all other backends
         _registeredStorageBackends.clear();
-        connect(storage.get(), SIGNAL(bufferInfoUpdated(UserId, const BufferInfo &)),
-                this, SIGNAL(bufferInfoUpdated(UserId, const BufferInfo &)));
+        connect(storage.get(), &Storage::bufferInfoUpdated, this, &Core::bufferInfoUpdated);
         break;
     }
     _storage = std::move(storage);
     return true;
 }
 
-
 void Core::syncStorage()
 {
     if (_storage)
         _storage->sync();
 }
 
-
 /*** Storage Access ***/
-bool Core::createNetwork(UserId user, NetworkInfo &info)
+bool Core::createNetwork(UserId user, NetworkInfoinfo)
 {
     NetworkId networkId = instance()->_storage->createNetwork(user, info);
     if (!networkId.isValid())
@@ -460,7 +493,6 @@ bool Core::createNetwork(UserId user, NetworkInfo &info)
     return true;
 }
 
-
 /*** Authenticators ***/
 
 // Authentication handling, now independent from storage.
@@ -474,7 +506,6 @@ void Core::registerAuthenticator()
         authenticator->deleteLater();
 }
 
-
 void Core::registerAuthenticators()
 {
     if (_registeredAuthenticators.empty()) {
@@ -485,25 +516,23 @@ void Core::registerAuthenticators()
     }
 }
 
-
-DeferredSharedPtr<Authenticator> Core::authenticator(const QString &backendId) const
+DeferredSharedPtr<Authenticator> Core::authenticator(const QString& backendId) const
 {
-    auto it = std::find_if(_registeredAuthenticators.begin(), _registeredAuthenticators.end(),
-                           [backendId](const DeferredSharedPtr<Authenticator> &authenticator) {
+    auto it = std::find_if(_registeredAuthenticators.begin(),
+                           _registeredAuthenticators.end(),
+                           [backendId](const DeferredSharedPtr<Authenticator>& authenticator) {
                                return authenticator->backendId() == backendId;
                            });
     return it != _registeredAuthenticators.end() ? *it : nullptr;
 }
 
-
 // FIXME: Apparently, this is the legacy way of initting storage backends?
 // If there's a not-legacy way, it should be used here
-bool Core::initAuthenticator(const QString &backend, const QVariantMap &settings,
-                             const QProcessEnvironment &environment, bool loadFromEnvironment,
-                             bool setup)
+bool Core::initAuthenticator(
+    const QString& backend, const QVariantMap& settings, const QProcessEnvironment& environment, bool loadFromEnvironment, bool setup)
 {
     if (backend.isEmpty()) {
-        quWarning() << "No authenticator selected!";
+        qWarning() << "No authenticator selected!";
         return false;
     }
 
@@ -522,12 +551,12 @@ bool Core::initAuthenticator(const QString &backend, const QVariantMap &settings
             return initAuthenticator(backend, settings, environment, loadFromEnvironment, false);
         return false;
 
-    // if initialization wasn't successful, we quit to keep from coming up unconfigured
     case Authenticator::NotAvailable:
-        qCritical() << "FATAL: Selected auth backend is not available:" << backend;
         if (!setup) {
-            QCoreApplication::exit(EXIT_FAILURE);
+            // If initialization wasn't successful, we quit to keep from coming up unconfigured
+            throw ExitException{EXIT_FAILURE, tr("Selected auth backend %1 is not available.").arg(backend)};
         }
+        qCritical() << "Selected auth backend is not available:" << backend;
         return false;
 
     case Authenticator::IsReady:
@@ -539,37 +568,21 @@ bool Core::initAuthenticator(const QString &backend, const QVariantMap &settings
     return true;
 }
 
-
 /*** Network Management ***/
 
 bool Core::sslSupported()
 {
-#ifdef HAVE_SSL
-    SslServer *sslServer = qobject_cast<SslServer *>(&instance()->_server);
-    return sslServer && sslServer->isCertValid();
-#else
-    return false;
-#endif
+    return instance()->_server.isCertValid() && instance()->_v6server.isCertValid();
 }
 
-
 bool Core::reloadCerts()
 {
-#ifdef HAVE_SSL
-    SslServer *sslServerv4 = qobject_cast<SslServer *>(&_server);
-    bool retv4 = sslServerv4->reloadCerts();
-
-    SslServer *sslServerv6 = qobject_cast<SslServer *>(&_v6server);
-    bool retv6 = sslServerv6->reloadCerts();
+    bool retv4 = _server.reloadCerts();
+    bool retv6 = _v6server.reloadCerts();
 
     return retv4 && retv6;
-#else
-    // SSL not supported, don't mark configuration reload as failed
-    return true;
-#endif
 }
 
-
 void Core::cacheSysIdent()
 {
     if (isConfigured()) {
@@ -577,7 +590,6 @@ void Core::cacheSysIdent()
     }
 }
 
-
 QString Core::strictSysIdent(UserId user) const
 {
     if (_authUserNames.contains(user)) {
@@ -594,10 +606,9 @@ QString Core::strictSysIdent(UserId user) const
 
     // ...something very weird is going on if we ended up here (an active CoreSession without a corresponding database entry?)
     qWarning().nospace() << "Unable to find authusername for UserId " << user << ", this should never happen!";
-    return "unknown"; // Should we just terminate the program instead?
+    return "unknown";  // Should we just terminate the program instead?
 }
 
-
 bool Core::startListening()
 {
     // in mono mode we only start a local port if a port is specified in the cli call
@@ -610,75 +621,68 @@ bool Core::startListening()
     const QString listen = Quassel::optionValue("listen");
     const QStringList listen_list = listen.split(",", QString::SkipEmptyParts);
     if (listen_list.size() > 0) {
-        foreach(const QString listen_term, listen_list) { // TODO: handle multiple interfaces for same TCP version gracefully
+        foreach (const QString listen_term, listen_list) {  // TODO: handle multiple interfaces for same TCP version gracefully
             QHostAddress addr;
             if (!addr.setAddress(listen_term)) {
-                qCritical() << qPrintable(
-                    tr("Invalid listen address %1")
-                    .arg(listen_term)
-                    );
+                qCritical() << qPrintable(tr("Invalid listen address %1").arg(listen_term));
             }
             else {
                 switch (addr.protocol()) {
                 case QAbstractSocket::IPv6Protocol:
                     if (_v6server.listen(addr, port)) {
-                        quInfo() << qPrintable(
-                            tr("Listening for GUI clients on IPv6 %1 port %2 using protocol version %3")
-                            .arg(addr.toString())
-                            .arg(_v6server.serverPort())
-                            .arg(Quassel::buildInfo().protocolVersion)
-                            );
+                        qInfo() << qPrintable(tr("Listening for GUI clients on IPv6 %1 port %2 using protocol version %3")
+                                              .arg(addr.toString())
+                                              .arg(_v6server.serverPort())
+                                              .arg(Quassel::buildInfo().protocolVersion));
                         success = true;
                     }
                     else
-                        quWarning() << qPrintable(
-                            tr("Could not open IPv6 interface %1:%2: %3")
-                            .arg(addr.toString())
-                            .arg(port)
-                            .arg(_v6server.errorString()));
+                        qWarning() << qPrintable(tr("Could not open IPv6 interface %1:%2: %3").arg(addr.toString()).arg(port).arg(_v6server.errorString()));
                     break;
                 case QAbstractSocket::IPv4Protocol:
                     if (_server.listen(addr, port)) {
-                        quInfo() << qPrintable(
-                            tr("Listening for GUI clients on IPv4 %1 port %2 using protocol version %3")
-                            .arg(addr.toString())
-                            .arg(_server.serverPort())
-                            .arg(Quassel::buildInfo().protocolVersion)
-                            );
+                        qInfo() << qPrintable(tr("Listening for GUI clients on IPv4 %1 port %2 using protocol version %3")
+                                              .arg(addr.toString())
+                                              .arg(_server.serverPort())
+                                              .arg(Quassel::buildInfo().protocolVersion));
                         success = true;
                     }
                     else {
                         // if v6 succeeded on Any, the port will be already in use - don't display the error then
                         if (!success || _server.serverError() != QAbstractSocket::AddressInUseError)
-                            quWarning() << qPrintable(
-                                tr("Could not open IPv4 interface %1:%2: %3")
-                                .arg(addr.toString())
-                                .arg(port)
-                                .arg(_server.errorString()));
+                            qWarning() << qPrintable(tr("Could not open IPv4 interface %1:%2: %3").arg(addr.toString()).arg(port).arg(_server.errorString()));
                     }
                     break;
                 default:
-                    qCritical() << qPrintable(
-                        tr("Invalid listen address %1, unknown network protocol")
-                        .arg(listen_term)
-                        );
+                    qCritical() << qPrintable(tr("Invalid listen address %1, unknown network protocol").arg(listen_term));
                     break;
                 }
             }
         }
     }
     if (!success)
-        quError() << qPrintable(tr("Could not open any network interfaces to listen on!"));
+        qCritical() << qPrintable(tr("Could not open any network interfaces to listen on!"));
+
+    if (_identServer) {
+        _identServer->startListening();
+    }
 
-    if (_identServer != nullptr) _identServer->startListening();
+    if (_metricsServer) {
+        _metricsServer->startListening();
+    }
 
     return success;
 }
 
-
-void Core::stopListening(const QString &reason)
+void Core::stopListening(const QString& reason)
 {
-    if (_identServer != nullptr) _identServer->stopListening(reason);
+    if (_identServer) {
+        _identServer->stopListening(reason);
+    }
+
+    if (_metricsServer) {
+        _metricsServer->stopListening(reason);
+    }
 
     bool wasListening = false;
     if (_server.isListening()) {
@@ -691,28 +695,28 @@ void Core::stopListening(const QString &reason)
     }
     if (wasListening) {
         if (reason.isEmpty())
-            quInfo() << "No longer listening for GUI clients.";
+            qInfo() << "No longer listening for GUI clients.";
         else
-            quInfo() << qPrintable(reason);
+            qInfo() << qPrintable(reason);
     }
 }
 
-
 void Core::incomingConnection()
 {
-    QTcpServer *server = qobject_cast<QTcpServer *>(sender());
+    auto* server = qobject_cast<SslServer*>(sender());
     Q_ASSERT(server);
     while (server->hasPendingConnections()) {
-        QTcpSocket *socket = server->nextPendingConnection();
+        auto socket = qobject_cast<QSslSocket*>(server->nextPendingConnection());
+        Q_ASSERT(socket);
 
-        CoreAuthHandler *handler = new CoreAuthHandler(socket, this);
+        auto* handler = new CoreAuthHandler(socket, this);
         _connectingClients.insert(handler);
 
-        connect(handler, SIGNAL(disconnected()), SLOT(clientDisconnected()));
-        connect(handler, SIGNAL(socketError(QAbstractSocket::SocketError,QString)), SLOT(socketError(QAbstractSocket::SocketError,QString)));
-        connect(handler, SIGNAL(handshakeComplete(RemotePeer*,UserId)), SLOT(setupClientSession(RemotePeer*,UserId)));
+        connect(handler, &AuthHandler::disconnected, this, &Core::clientDisconnected);
+        connect(handler, &AuthHandler::socketError, this, &Core::socketError);
+        connect(handler, &CoreAuthHandler::handshakeComplete, this, &Core::setupClientSession);
 
-        quInfo() << qPrintable(tr("Client connected from"))  << qPrintable(socket->peerAddress().toString());
+        qInfo() << qPrintable(tr("Client connected from")) << qPrintable(handler->hostAddress().toString());
 
         if (!_configured) {
             stopListening(tr("Closing server for basic setup."));
@@ -720,14 +724,13 @@ void Core::incomingConnection()
     }
 }
 
-
 // Potentially called during the initialization phase (before handing the connection off to the session)
 void Core::clientDisconnected()
 {
-    CoreAuthHandler *handler = qobject_cast<CoreAuthHandler *>(sender());
+    auto* handler = qobject_cast<CoreAuthHandler*>(sender());
     Q_ASSERT(handler);
 
-    quInfo() << qPrintable(tr("Non-authed client disconnected:")) << qPrintable(handler->socket()->peerAddress().toString());
+    qInfo() << qPrintable(tr("Non-authed client disconnected:")) << qPrintable(handler->hostAddress().toString());
     _connectingClients.remove(handler);
     handler->deleteLater();
 
@@ -740,14 +743,13 @@ void Core::clientDisconnected()
     // Suggestion: kill sessions if they are not connected to any network and client.
 }
 
-
-void Core::setupClientSession(RemotePeer *peer, UserId uid)
+void Core::setupClientSession(RemotePeer* peer, UserId uid)
 {
-    CoreAuthHandler *handler = qobject_cast<CoreAuthHandler *>(sender());
+    auto* handler = qobject_cast<CoreAuthHandler*>(sender());
     Q_ASSERT(handler);
 
     // From now on everything is handled by the client session
-    disconnect(handler, 0, this, 0);
+    disconnect(handler, nullptr, this, nullptr);
     _connectingClients.remove(handler);
     handler->deleteLater();
 
@@ -759,25 +761,22 @@ void Core::setupClientSession(RemotePeer *peer, UserId uid)
     QCoreApplication::postEvent(this, new AddClientEvent(peer, uid));
 }
 
-
-void Core::customEvent(QEvent *event)
+void Core::customEvent(QEvent* event)
 {
     if (event->type() == AddClientEventId) {
-        AddClientEvent *addClientEvent = static_cast<AddClientEvent *>(event);
+        auto* addClientEvent = static_cast<AddClientEvent*>(event);
         addClientHelper(addClientEvent->peer, addClientEvent->userId);
         return;
     }
 }
 
-
-void Core::addClientHelper(RemotePeer *peer, UserId uid)
+void Core::addClientHelper(RemotePeer* peer, UserId uid)
 {
     // Find or create session for validated user
-    SessionThread *session = sessionForUser(uid);
+    SessionThreadsession = sessionForUser(uid);
     session->addClient(peer);
 }
 
-
 void Core::connectInternalPeer(QPointer<InternalPeer> peer)
 {
     if (_initialized && peer) {
@@ -788,12 +787,15 @@ void Core::connectInternalPeer(QPointer<InternalPeer> peer)
     }
 }
 
-
 void Core::setupInternalClientSession(QPointer<InternalPeer> clientPeer)
 {
     if (!_configured) {
         stopListening();
-        setupCoreForInternalUsage();
+        auto errorString = setupCoreForInternalUsage();
+        if (!errorString.isEmpty()) {
+            emit exitRequested(EXIT_FAILURE, errorString);
+            return;
+        }
     }
 
     UserId uid;
@@ -801,105 +803,98 @@ void Core::setupInternalClientSession(QPointer<InternalPeer> clientPeer)
         uid = _storage->internalUser();
     }
     else {
-        quWarning() << "Core::setupInternalClientSession(): You're trying to run monolithic Quassel with an unusable Backend! Go fix it!";
-        QCoreApplication::exit(EXIT_FAILURE);
+        qWarning() << "Core::setupInternalClientSession(): You're trying to run monolithic Quassel with an unusable Backend! Go fix it!";
+        emit exitRequested(EXIT_FAILURE, tr("Cannot setup storage backend."));
         return;
     }
 
     if (!clientPeer) {
-        quWarning() << "Client peer went away, not starting a session";
+        qWarning() << "Client peer went away, not starting a session";
         return;
     }
 
-    InternalPeer *corePeer = new InternalPeer(this);
+    auto* corePeer = new InternalPeer(this);
     corePeer->setPeer(clientPeer);
     clientPeer->setPeer(corePeer);
 
     // Find or create session for validated user
-    SessionThread *sessionThread = sessionForUser(uid);
+    SessionThreadsessionThread = sessionForUser(uid);
     sessionThread->addClient(corePeer);
 }
 
-
-SessionThread *Core::sessionForUser(UserId uid, bool restore)
+SessionThread* Core::sessionForUser(UserId uid, bool restore)
 {
     if (_sessions.contains(uid))
         return _sessions[uid];
 
-    SessionThread *session = new SessionThread(uid, restore, strictIdentEnabled(), this);
-    _sessions[uid] = session;
-    session->start();
-    return session;
+    return (_sessions[uid] = new SessionThread(uid, restore, strictIdentEnabled(), this));
 }
 
-
-void Core::socketError(QAbstractSocket::SocketError err, const QString &errorString)
+void Core::socketError(QAbstractSocket::SocketError err, const QString& errorString)
 {
-    quWarning() << QString("Socket error %1: %2").arg(err).arg(errorString);
+    qWarning() << QString("Socket error %1: %2").arg(err).arg(errorString);
 }
 
-
 QVariantList Core::backendInfo()
 {
     instance()->registerStorageBackends();
 
     QVariantList backendInfos;
-    for (auto &&backend : instance()->_registeredStorageBackends) {
+    for (auto&& backend : instance()->_registeredStorageBackends) {
         QVariantMap v;
-        v["BackendId"]   = backend->backendId();
+        v["BackendId"] = backend->backendId();
         v["DisplayName"] = backend->displayName();
         v["Description"] = backend->description();
-        v["SetupData"]   = backend->setupData(); // ignored by legacy clients
+        v["SetupData"] = backend->setupData();  // ignored by legacy clients
 
         // TODO Protocol Break: Remove legacy (cf. authenticatorInfo())
-        const auto &setupData = backend->setupData();
+        const autosetupData = backend->setupData();
         QStringList setupKeys;
         QVariantMap setupDefaults;
         for (int i = 0; i + 2 < setupData.size(); i += 3) {
             setupKeys << setupData[i].toString();
             setupDefaults[setupData[i].toString()] = setupData[i + 2];
         }
-        v["SetupKeys"]     = setupKeys;
+        v["SetupKeys"] = setupKeys;
         v["SetupDefaults"] = setupDefaults;
         // TODO Protocol Break: Remove
-        v["IsDefault"]     = (backend->backendId() == "SQLite"); // newer clients will just use the first in the list
+        v["IsDefault"] = (backend->backendId() == "SQLite");  // newer clients will just use the first in the list
 
         backendInfos << v;
     }
     return backendInfos;
 }
 
-
 QVariantList Core::authenticatorInfo()
 {
     instance()->registerAuthenticators();
 
     QVariantList authInfos;
-    for(auto &&backend : instance()->_registeredAuthenticators) {
+    for (auto&& backend : instance()->_registeredAuthenticators) {
         QVariantMap v;
-        v["BackendId"]   = backend->backendId();
+        v["BackendId"] = backend->backendId();
         v["DisplayName"] = backend->displayName();
         v["Description"] = backend->description();
-        v["SetupData"]   = backend->setupData();
+        v["SetupData"] = backend->setupData();
         authInfos << v;
     }
     return authInfos;
 }
 
 // migration / backend selection
-bool Core::selectBackend(const QString &backend)
+bool Core::selectBackend(const QStringbackend)
 {
     // reregister all storage backends
     registerStorageBackends();
     auto storage = storageBackend(backend);
     if (!storage) {
         QStringList backends;
-        std::transform(_registeredStorageBackends.begin(), _registeredStorageBackends.end(),
-                       std::back_inserter(backends), [](const DeferredSharedPtr<Storage>& backend) {
-                           return backend->displayName();
-                       });
-        quWarning() << qPrintable(tr("Unsupported storage backend: %1").arg(backend));
-        quWarning() << qPrintable(tr("Supported backends are:")) << qPrintable(backends.join(", "));
+        std::transform(_registeredStorageBackends.begin(),
+                       _registeredStorageBackends.end(),
+                       std::back_inserter(backends),
+                       [](const DeferredSharedPtr<Storage>& backend) { return backend->displayName(); });
+        qWarning() << qPrintable(tr("Unsupported storage backend: %1").arg(backend));
+        qWarning() << qPrintable(tr("Supported backends are:")) << qPrintable(backends.join(", "));
         return false;
     }
 
@@ -911,27 +906,27 @@ bool Core::selectBackend(const QString &backend)
         if (!saveBackendSettings(backend, settings)) {
             qCritical() << qPrintable(QString("Could not save backend settings, probably a permission problem."));
         }
-        quWarning() << qPrintable(tr("Switched storage backend to: %1").arg(backend));
-        quWarning() << qPrintable(tr("Backend already initialized. Skipping Migration..."));
+        qWarning() << qPrintable(tr("Switched storage backend to: %1").arg(backend));
+        qWarning() << qPrintable(tr("Backend already initialized. Skipping Migration..."));
         return true;
     case Storage::NotAvailable:
         qCritical() << qPrintable(tr("Storage backend is not available: %1").arg(backend));
         return false;
     case Storage::NeedsSetup:
         if (!storage->setup(settings)) {
-            quWarning() << qPrintable(tr("Unable to setup storage backend: %1").arg(backend));
+            qWarning() << qPrintable(tr("Unable to setup storage backend: %1").arg(backend));
             return false;
         }
 
         if (storage->init(settings) != Storage::IsReady) {
-            quWarning() << qPrintable(tr("Unable to initialize storage backend: %1").arg(backend));
+            qWarning() << qPrintable(tr("Unable to initialize storage backend: %1").arg(backend));
             return false;
         }
 
         if (!saveBackendSettings(backend, settings)) {
             qCritical() << qPrintable(QString("Could not save backend settings, probably a permission problem."));
         }
-        quWarning() << qPrintable(tr("Switched storage backend to: %1").arg(backend));
+        qWarning() << qPrintable(tr("Switched storage backend to: %1").arg(backend));
         break;
     }
 
@@ -951,19 +946,19 @@ bool Core::selectBackend(const QString &backend)
             }
             return true;
         }
-        quWarning() << qPrintable(tr("Unable to migrate storage backend! (No migration writer for %1)").arg(backend));
+        qWarning() << qPrintable(tr("Unable to migrate storage backend! (No migration writer for %1)").arg(backend));
         return false;
     }
 
     // inform the user why we cannot merge
     if (!_storage) {
-        quWarning() << qPrintable(tr("No currently active storage backend. Skipping migration..."));
+        qWarning() << qPrintable(tr("No currently active storage backend. Skipping migration..."));
     }
     else if (!reader) {
-        quWarning() << qPrintable(tr("Currently active storage backend does not support migration: %1").arg(_storage->displayName()));
+        qWarning() << qPrintable(tr("Currently active storage backend does not support migration: %1").arg(_storage->displayName()));
     }
     if (writer) {
-        quWarning() << qPrintable(tr("New storage backend does not support migration: %1").arg(backend));
+        qWarning() << qPrintable(tr("New storage backend does not support migration: %1").arg(backend));
     }
 
     // so we were unable to merge, but let's create a user \o/
@@ -974,19 +969,19 @@ bool Core::selectBackend(const QString &backend)
 
 // TODO: I am not sure if this function is implemented correctly.
 // There is currently no concept of migraiton between auth backends.
-bool Core::selectAuthenticator(const QString &backend)
+bool Core::selectAuthenticator(const QStringbackend)
 {
     // Register all authentication backends.
     registerAuthenticators();
     auto auther = authenticator(backend);
     if (!auther) {
         QStringList authenticators;
-        std::transform(_registeredAuthenticators.begin(), _registeredAuthenticators.end(),
-                       std::back_inserter(authenticators), [](const DeferredSharedPtr<Authenticator>& authenticator) {
-                           return authenticator->displayName();
-                       });
-        quWarning() << qPrintable(tr("Unsupported authenticator: %1").arg(backend));
-        quWarning() << qPrintable(tr("Supported authenticators are:")) << qPrintable(authenticators.join(", "));
+        std::transform(_registeredAuthenticators.begin(),
+                       _registeredAuthenticators.end(),
+                       std::back_inserter(authenticators),
+                       [](const DeferredSharedPtr<Authenticator>& authenticator) { return authenticator->displayName(); });
+        qWarning() << qPrintable(tr("Unsupported authenticator: %1").arg(backend));
+        qWarning() << qPrintable(tr("Supported authenticators are:")) << qPrintable(authenticators.join(", "));
         return false;
     }
 
@@ -996,31 +991,30 @@ bool Core::selectAuthenticator(const QString &backend)
     switch (state) {
     case Authenticator::IsReady:
         saveAuthenticatorSettings(backend, settings);
-        quWarning() << qPrintable(tr("Switched authenticator to: %1").arg(backend));
+        qWarning() << qPrintable(tr("Switched authenticator to: %1").arg(backend));
         return true;
     case Authenticator::NotAvailable:
         qCritical() << qPrintable(tr("Authenticator is not available: %1").arg(backend));
         return false;
     case Authenticator::NeedsSetup:
         if (!auther->setup(settings)) {
-            quWarning() << qPrintable(tr("Unable to setup authenticator: %1").arg(backend));
+            qWarning() << qPrintable(tr("Unable to setup authenticator: %1").arg(backend));
             return false;
         }
 
         if (auther->init(settings) != Authenticator::IsReady) {
-            quWarning() << qPrintable(tr("Unable to initialize authenticator: %1").arg(backend));
+            qWarning() << qPrintable(tr("Unable to initialize authenticator: %1").arg(backend));
             return false;
         }
 
         saveAuthenticatorSettings(backend, settings);
-        quWarning() << qPrintable(tr("Switched authenticator to: %1").arg(backend));
+        qWarning() << qPrintable(tr("Switched authenticator to: %1").arg(backend));
     }
 
     _authenticator = std::move(auther);
     return true;
 }
 
-
 bool Core::createUser()
 {
     QTextStream out(stdout);
@@ -1042,11 +1036,11 @@ bool Core::createUser()
     enableStdInEcho();
 
     if (password != password2) {
-        quWarning() << "Passwords don't match!";
+        qWarning() << "Passwords don't match!";
         return false;
     }
     if (password.isEmpty()) {
-        quWarning() << "Password is empty!";
+        qWarning() << "Password is empty!";
         return false;
     }
 
@@ -1055,13 +1049,12 @@ bool Core::createUser()
         return true;
     }
     else {
-        quWarning() << "Unable to add user:" << qPrintable(username);
+        qWarning() << "Unable to add user:" << qPrintable(username);
         return false;
     }
 }
 
-
-bool Core::changeUserPass(const QString &username)
+bool Core::changeUserPass(const QString& username)
 {
     QTextStream out(stdout);
     QTextStream in(stdin);
@@ -1090,11 +1083,11 @@ bool Core::changeUserPass(const QString &username)
     enableStdInEcho();
 
     if (password != password2) {
-        quWarning() << "Passwords don't match!";
+        qWarning() << "Passwords don't match!";
         return false;
     }
     if (password.isEmpty()) {
-        quWarning() << "Password is empty!";
+        qWarning() << "Password is empty!";
         return false;
     }
 
@@ -1103,13 +1096,12 @@ bool Core::changeUserPass(const QString &username)
         return true;
     }
     else {
-        quWarning() << "Failed to change password!";
+        qWarning() << "Failed to change password!";
         return false;
     }
 }
 
-
-bool Core::changeUserPassword(UserId userId, const QString &password)
+bool Core::changeUserPassword(UserId userId, const QString& password)
 {
     if (!isConfigured() || !userId.isValid())
         return false;
@@ -1138,13 +1130,12 @@ bool Core::canChangeUserPassword(UserId userId)
     return true;
 }
 
-
-std::unique_ptr<AbstractSqlMigrationReader> Core::getMigrationReader(Storage *storage)
+std::unique_ptr<AbstractSqlMigrationReader> Core::getMigrationReader(Storage* storage)
 {
     if (!storage)
         return nullptr;
 
-    AbstractSqlStorage *sqlStorage = qobject_cast<AbstractSqlStorage *>(storage);
+    auto* sqlStorage = qobject_cast<AbstractSqlStorage*>(storage);
     if (!sqlStorage) {
         qDebug() << "Core::migrateDb(): only SQL based backends can be migrated!";
         return nullptr;
@@ -1153,13 +1144,12 @@ std::unique_ptr<AbstractSqlMigrationReader> Core::getMigrationReader(Storage *st
     return sqlStorage->createMigrationReader();
 }
 
-
-std::unique_ptr<AbstractSqlMigrationWriter> Core::getMigrationWriter(Storage *storage)
+std::unique_ptr<AbstractSqlMigrationWriter> Core::getMigrationWriter(Storage* storage)
 {
     if (!storage)
         return nullptr;
 
-    AbstractSqlStorage *sqlStorage = qobject_cast<AbstractSqlStorage *>(storage);
+    auto* sqlStorage = qobject_cast<AbstractSqlStorage*>(storage);
     if (!sqlStorage) {
         qDebug() << "Core::migrateDb(): only SQL based backends can be migrated!";
         return nullptr;
@@ -1168,8 +1158,7 @@ std::unique_ptr<AbstractSqlMigrationWriter> Core::getMigrationWriter(Storage *st
     return sqlStorage->createMigrationWriter();
 }
 
-
-bool Core::saveBackendSettings(const QString &backend, const QVariantMap &settings)
+bool Core::saveBackendSettings(const QString& backend, const QVariantMap& settings)
 {
     QVariantMap dbsettings;
     dbsettings["Backend"] = backend;
@@ -1179,8 +1168,7 @@ bool Core::saveBackendSettings(const QString &backend, const QVariantMap &settin
     return s.sync();
 }
 
-
-void Core::saveAuthenticatorSettings(const QString &backend, const QVariantMap &settings)
+void Core::saveAuthenticatorSettings(const QString& backend, const QVariantMap& settings)
 {
     QVariantMap dbsettings;
     dbsettings["Authenticator"] = backend;
@@ -1191,7 +1179,7 @@ void Core::saveAuthenticatorSettings(const QString &backend, const QVariantMap &
 // Generic version of promptForSettings that doesn't care what *type* of
 // backend it runs over.
 template<typename Backend>
-QVariantMap Core::promptForSettings(const Backend *backend)
+QVariantMap Core::promptForSettings(const Backendbackend)
 {
     QVariantMap settings;
     const QVariantList& setupData = backend->setupData();
@@ -1205,7 +1193,7 @@ QVariantMap Core::promptForSettings(const Backend *backend)
 
     for (int i = 0; i + 2 < setupData.size(); i += 3) {
         QString key = setupData[i].toString();
-        out << setupData[i+1].toString() << " [" << setupData[i+2].toString() << "]: " << flush;
+        out << setupData[i + 1].toString() << " [" << setupData[i + 2].toString() << "]: " << flush;
 
         bool noEcho = key.toLower().contains("password");
         if (noEcho) {
@@ -1217,7 +1205,7 @@ QVariantMap Core::promptForSettings(const Backend *backend)
             enableStdInEcho();
         }
 
-        QVariant value{setupData[i+2]};
+        QVariant value{setupData[i + 2]};
         if (!input.isEmpty()) {
             switch (value.type()) {
             case QVariant::Int:
@@ -1232,7 +1220,6 @@ QVariantMap Core::promptForSettings(const Backend *backend)
     return settings;
 }
 
-
 #ifdef Q_OS_WIN
 void Core::stdInEcho(bool on)
 {