X-Git-Url: https://git.quassel-irc.org/?p=quassel.git;a=blobdiff_plain;f=src%2Fcore%2Fcore.cpp;h=b103b42d80c5f7096f55ea62948f20c70a738a5d;hp=80646c0335e52ee5261c3ce77e369203b5ebc5c9;hb=9f2fbea7c308914d0b737ec9a936a004d4687223;hpb=27df512ce272d88cf85b854f6bfb3f1c7ba4a65c diff --git a/src/core/core.cpp b/src/core/core.cpp index 80646c03..b103b42d 100644 --- a/src/core/core.cpp +++ b/src/core/core.cpp @@ -66,25 +66,41 @@ public: // ============================== // Core // ============================== -Core *Core::instanceptr = 0; +Core *Core::_instance{nullptr}; Core *Core::instance() { - if (instanceptr) return instanceptr; - instanceptr = new Core(); - instanceptr->init(); - return instanceptr; + return _instance; } -void Core::destroy() +Core::Core() { - delete instanceptr; - instanceptr = 0; + if (_instance) { + qWarning() << "Recreating core instance!"; + delete _instance; + } + _instance = this; + + // Parent all QObject-derived attributes, so when the Core instance gets moved into another + // thread, they get moved with it + _server.setParent(this); + _v6server.setParent(this); + _storageSyncTimer.setParent(this); } -Core::Core() +Core::~Core() +{ + saveState(); + qDeleteAll(_connectingClients); + qDeleteAll(_sessions); + syncStorage(); + _instance = nullptr; +} + + +bool Core::init() { _startTime = QDateTime::currentDateTime().toUTC(); // for uptime :) @@ -95,20 +111,14 @@ Core::Core() CoreSettings s; if (s.version() != 1) { qCritical() << "Invalid core settings version, terminating!"; - exit(EXIT_FAILURE); + QCoreApplication::exit(EXIT_FAILURE); + return false; } // Set up storage and authentication backends registerStorageBackends(); registerAuthenticators(); - connect(&_storageSyncTimer, SIGNAL(timeout()), this, SLOT(syncStorage())); - _storageSyncTimer.start(10 * 60 * 1000); // 10 minutes -} - - -void Core::init() -{ QProcessEnvironment environment = QProcessEnvironment::systemEnvironment(); bool config_from_environment = Quassel::isOptionSet("config-from-environment"); @@ -146,13 +156,15 @@ void Core::init() } if (Quassel::isOptionSet("select-backend") || Quassel::isOptionSet("select-authenticator")) { + bool success{true}; if (Quassel::isOptionSet("select-backend")) { - selectBackend(Quassel::optionValue("select-backend")); + success &= selectBackend(Quassel::optionValue("select-backend")); } if (Quassel::isOptionSet("select-authenticator")) { - selectAuthenticator(Quassel::optionValue("select-authenticator")); + success &= selectAuthenticator(Quassel::optionValue("select-authenticator")); } - exit(EXIT_SUCCESS); + QCoreApplication::exit(success ? EXIT_SUCCESS : EXIT_FAILURE); + return success; } if (!_configured) { @@ -162,82 +174,105 @@ void Core::init() if (!_configured) { qWarning() << "Cannot configure from environment"; - exit(EXIT_FAILURE); + QCoreApplication::exit(EXIT_FAILURE); + return false; } - } else { + } + 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.")); - exit(EXIT_FAILURE); // TODO make this less brutal (especially for mono client -> popup) + QCoreApplication::exit(EXIT_FAILURE); // TODO make this less brutal (especially for mono client -> popup) + return false; } - quWarning() << "Core is currently not configured! Please connect with a Quassel Client for basic setup."; if (writeError) { qWarning() << "Cannot write quasselcore configuration; probably a permission problem."; - exit(EXIT_FAILURE); + QCoreApplication::exit(EXIT_FAILURE); + return false; } + + quInfo() << "Core is currently not configured! Please connect with a Quassel Client for basic setup."; } } + else { + if (Quassel::isOptionSet("add-user")) { + bool success = createUser(); + QCoreApplication::exit(success ? EXIT_SUCCESS : EXIT_FAILURE); + return success; + } - if (Quassel::isOptionSet("add-user")) { - exit(createUser() ? 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; + } - } + _strictIdentEnabled = Quassel::isOptionSet("strict-ident"); + if (_strictIdentEnabled) { + cacheSysIdent(); + } + + if (Quassel::isOptionSet("oidentd")) { + _oidentdConfigGenerator = new OidentdConfigGenerator(this); + } + + Quassel::registerReloadHandler([]() { + // Currently, only reloading SSL certificates and the sysident cache is supported + if (Core::instance()) { + Core::instance()->cacheSysIdent(); + Core::instance()->reloadCerts(); + return true; + } + return false; + }); - if (Quassel::isOptionSet("change-userpass")) { - exit(changeUserPass(Quassel::optionValue("change-userpass")) ? - EXIT_SUCCESS : EXIT_FAILURE); + connect(&_storageSyncTimer, SIGNAL(timeout()), this, SLOT(syncStorage())); + _storageSyncTimer.start(10 * 60 * 1000); // 10 minutes } connect(&_server, SIGNAL(newConnection()), this, SLOT(incomingConnection())); connect(&_v6server, SIGNAL(newConnection()), this, SLOT(incomingConnection())); - if (!startListening()) exit(1); // TODO make this less brutal - _strictIdentEnabled = Quassel::isOptionSet("strict-ident"); - if (_strictIdentEnabled) { - cacheSysIdent(); + if (!startListening()) { + QCoreApplication::exit(EXIT_FAILURE); // TODO make this less brutal + return false; } - if (Quassel::isOptionSet("oidentd")) { - _oidentdConfigGenerator = new OidentdConfigGenerator(this); + if (_configured && !Quassel::isOptionSet("norestore")) { + Core::restoreState(); } -} - -Core::~Core() -{ - // FIXME do we need more cleanup for handlers? - foreach(CoreAuthHandler *handler, _connectingClients) { - handler->deleteLater(); // disconnect non authed clients - } - qDeleteAll(_sessions); + return true; } - /*** Session Restore ***/ void Core::saveState() { - QVariantList activeSessions; - foreach(UserId user, instance()->_sessions.keys()) - activeSessions << QVariant::fromValue(user); - instance()->_storage->setCoreState(activeSessions); + if (_storage) { + QVariantList activeSessions; + for (auto &&user : instance()->_sessions.keys()) + activeSessions << QVariant::fromValue(user); + _storage->setCoreState(activeSessions); + } } void Core::restoreState() { - if (!instance()->_configured) { - // quWarning() << qPrintable(tr("Cannot restore a state for an unconfigured core!")); + if (!_configured) { + quWarning() << qPrintable(tr("Cannot restore a state for an unconfigured core!")); return; } - if (instance()->_sessions.count()) { + if (_sessions.count()) { quWarning() << qPrintable(tr("Calling restoreState() even though active sessions exist!")); return; } + CoreSettings s; /* We don't check, since we are at the first version since switching to Git uint statever = s.coreState().toMap()["CoreStateVersion"].toUInt(); @@ -252,9 +287,9 @@ void Core::restoreState() if (activeSessions.count() > 0) { quInfo() << "Restoring previous core state..."; - foreach(QVariant v, activeSessions) { + for(auto &&v : activeSessions) { UserId user = v.value(); - instance()->sessionForUser(user, true); + sessionForUser(user, true); } } } @@ -374,8 +409,9 @@ bool Core::initStorage(const QString &backend, const QVariantMap &settings, // 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) - exit(EXIT_FAILURE); + if (!setup) { + QCoreApplication::exit(EXIT_FAILURE); + } return false; case Storage::IsReady: @@ -473,8 +509,9 @@ bool Core::initAuthenticator(const QString &backend, const QVariantMap &settings // 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) - exit(EXIT_FAILURE); + if (!setup) { + QCoreApplication::exit(EXIT_FAILURE); + } return false; case Authenticator::IsReady: @@ -503,10 +540,10 @@ bool Core::sslSupported() bool Core::reloadCerts() { #ifdef HAVE_SSL - SslServer *sslServerv4 = qobject_cast(&instance()->_server); + SslServer *sslServerv4 = qobject_cast(&_server); bool retv4 = sslServerv4->reloadCerts(); - SslServer *sslServerv6 = qobject_cast(&instance()->_v6server); + SslServer *sslServerv6 = qobject_cast(&_v6server); bool retv6 = sslServerv6->reloadCerts(); return retv4 && retv6; @@ -520,7 +557,7 @@ bool Core::reloadCerts() void Core::cacheSysIdent() { if (isConfigured()) { - instance()->_authUserNames = instance()->_storage->getAllAuthUserNames(); + _authUserNames = _storage->getAllAuthUserNames(); } } @@ -533,7 +570,7 @@ QString Core::strictSysIdent(UserId user) const // A new user got added since we last pulled our cache from the database. // There's no way to avoid a database hit - we don't even know the authname! - cacheSysIdent(); + instance()->cacheSysIdent(); if (_authUserNames.contains(user)) { return _authUserNames[user];