Move all core initialization into Core::init(), including things
that were previously done in CoreApplication and MonoApplication.
Make several functions private and non-static that no longer need
to be called from the outside.
Allow to construct and destroy the core directly, rather than
relying on Core::instance() and Core::destroy(). Explicitly
create and destroy the instance in the application to better control
lifetime.
Ensure core state is saved and storage synced on destruction, instead
of relying on explicit calls (which were partially missing for mono).
// ==============================
// Core
// ==============================
// ==============================
// Core
// ==============================
-Core *Core::instanceptr = 0;
+Core *Core::_instance{nullptr};
- if (instanceptr) return instanceptr;
- instanceptr = new Core();
- instanceptr->init();
- return instanceptr;
- delete instanceptr;
- instanceptr = 0;
+ if (_instance) {
+ qWarning() << "Recreating core instance!";
+ delete _instance;
+ }
+ _instance = this;
+Core::~Core()
+{
+ saveState();
+ qDeleteAll(_connectingClients);
+ qDeleteAll(_sessions);
+ syncStorage();
+ _instance = nullptr;
+}
+
+
+bool Core::init()
{
_startTime = QDateTime::currentDateTime().toUTC(); // for uptime :)
{
_startTime = QDateTime::currentDateTime().toUTC(); // for uptime :)
registerStorageBackends();
registerAuthenticators();
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");
QProcessEnvironment environment = QProcessEnvironment::systemEnvironment();
bool config_from_environment = Quassel::isOptionSet("config-from-environment");
qWarning() << "Cannot configure from environment";
exit(EXIT_FAILURE);
}
qWarning() << "Cannot configure from environment";
exit(EXIT_FAILURE);
}
if (_registeredStorageBackends.empty()) {
quWarning() << qPrintable(tr("Could not initialize any storage backend! Exiting..."));
quWarning()
if (_registeredStorageBackends.empty()) {
quWarning() << qPrintable(tr("Could not initialize any storage backend! Exiting..."));
quWarning()
"to work."));
exit(EXIT_FAILURE); // TODO make this less brutal (especially for mono client -> popup)
}
"to work."));
exit(EXIT_FAILURE); // TODO make this less brutal (especially for mono client -> popup)
}
- 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);
}
if (writeError) {
qWarning() << "Cannot write quasselcore configuration; probably a permission problem.";
exit(EXIT_FAILURE);
}
+
+ quInfo() << "Core is currently not configured! Please connect with a Quassel Client for basic setup.";
+ else {
+ if (Quassel::isOptionSet("add-user")) {
+ exit(createUser() ? EXIT_SUCCESS : EXIT_FAILURE);
+ }
- if (Quassel::isOptionSet("add-user")) {
- exit(createUser() ? EXIT_SUCCESS : EXIT_FAILURE);
+ if (Quassel::isOptionSet("change-userpass")) {
+ exit(changeUserPass(Quassel::optionValue("change-userpass")) ? EXIT_SUCCESS : EXIT_FAILURE);
+ }
+ _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()));
}
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()) {
+ exit(EXIT_FAILURE); // TODO make this less brutal
- 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);
/*** Session Restore ***/
void Core::saveState()
{
/*** Session Restore ***/
void Core::saveState()
{
- QVariantList activeSessions;
- foreach(UserId user, instance()->_sessions.keys())
- activeSessions << QVariant::fromValue<UserId>(user);
- instance()->_storage->setCoreState(activeSessions);
+ if (_storage) {
+ QVariantList activeSessions;
+ for (auto &&user : instance()->_sessions.keys())
+ activeSessions << QVariant::fromValue<UserId>(user);
+ _storage->setCoreState(activeSessions);
+ }
}
void Core::restoreState()
{
}
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!"));
- if (instance()->_sessions.count()) {
+ if (_sessions.count()) {
quWarning() << qPrintable(tr("Calling restoreState() even though active sessions exist!"));
return;
}
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();
CoreSettings s;
/* We don't check, since we are at the first version since switching to Git
uint statever = s.coreState().toMap()["CoreStateVersion"].toUInt();
if (activeSessions.count() > 0) {
quInfo() << "Restoring previous core state...";
if (activeSessions.count() > 0) {
quInfo() << "Restoring previous core state...";
- foreach(QVariant v, activeSessions) {
+ for(auto &&v : activeSessions) {
UserId user = v.value<UserId>();
UserId user = v.value<UserId>();
- instance()->sessionForUser(user, true);
+ sessionForUser(user, true);
bool Core::reloadCerts()
{
#ifdef HAVE_SSL
bool Core::reloadCerts()
{
#ifdef HAVE_SSL
- SslServer *sslServerv4 = qobject_cast<SslServer *>(&instance()->_server);
+ SslServer *sslServerv4 = qobject_cast<SslServer *>(&_server);
bool retv4 = sslServerv4->reloadCerts();
bool retv4 = sslServerv4->reloadCerts();
- SslServer *sslServerv6 = qobject_cast<SslServer *>(&instance()->_v6server);
+ SslServer *sslServerv6 = qobject_cast<SslServer *>(&_v6server);
bool retv6 = sslServerv6->reloadCerts();
return retv4 && retv6;
bool retv6 = sslServerv6->reloadCerts();
return retv4 && retv6;
void Core::cacheSysIdent()
{
if (isConfigured()) {
void Core::cacheSysIdent()
{
if (isConfigured()) {
- instance()->_authUserNames = instance()->_storage->getAllAuthUserNames();
+ _authUserNames = _storage->getAllAuthUserNames();
// 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!
// 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!
+ instance()->cacheSysIdent();
if (_authUserNames.contains(user)) {
return _authUserNames[user];
if (_authUserNames.contains(user)) {
return _authUserNames[user];
public:
static Core *instance();
public:
static Core *instance();
- static void saveState();
- static void restoreState();
+ Core();
+ ~Core() override;
/*** Storage access ***/
// These methods are threadsafe.
/*** Storage access ***/
// These methods are threadsafe.
static bool sslSupported();
static bool sslSupported();
- /**
- * Reloads SSL certificates used for connection with clients
- *
- * @return True if certificates reloaded successfully, otherwise false.
- */
- static bool reloadCerts();
-
- static void cacheSysIdent();
-
static QVariantList backendInfo();
static QVariantList authenticatorInfo();
static QVariantList backendInfo();
static QVariantList authenticatorInfo();
static const int AddClientEventId;
public slots:
static const int AddClientEventId;
public slots:
- //! Make storage data persistent
- /** \note This method is threadsafe.
+ bool init();
+
+ /** Persist storage.
+ *
+ * @note This method is threadsafe.
+
+ /**
+ * Reload SSL certificates used for connection with clients.
+ *
+ * @return True if certificates reloaded successfully, otherwise false.
+ */
+ bool reloadCerts();
+
+ void cacheSysIdent();
+
void setupInternalClientSession(InternalPeer *clientConnection);
QString setupCore(const QString &adminUser, const QString &adminPassword, const QString &backend, const QVariantMap &setupData, const QString &authenticator, const QVariantMap &authSetupMap);
void setupInternalClientSession(InternalPeer *clientConnection);
QString setupCore(const QString &adminUser, const QString &adminPassword, const QString &backend, const QVariantMap &setupData, const QString &authenticator, const QVariantMap &authSetupMap);
void sessionState(const Protocol::SessionState &sessionState);
protected:
void sessionState(const Protocol::SessionState &sessionState);
protected:
- virtual void customEvent(QEvent *event);
+ void customEvent(QEvent *event) override;
private slots:
bool startListening();
private slots:
bool startListening();
bool changeUserPass(const QString &username);
private:
bool changeUserPass(const QString &username);
private:
- Core();
- ~Core();
- void init();
- static Core *instanceptr;
-
SessionThread *sessionForUser(UserId userId, bool restoreState = false);
void addClientHelper(RemotePeer *peer, UserId uid);
//void processCoreSetup(QTcpSocket *socket, QVariantMap &msg);
SessionThread *sessionForUser(UserId userId, bool restoreState = false);
void addClientHelper(RemotePeer *peer, UserId uid);
//void processCoreSetup(QTcpSocket *socket, QVariantMap &msg);
bool saveBackendSettings(const QString &backend, const QVariantMap &settings);
void saveAuthenticatorSettings(const QString &backend, const QVariantMap &settings);
bool saveBackendSettings(const QString &backend, const QVariantMap &settings);
void saveAuthenticatorSettings(const QString &backend, const QVariantMap &settings);
+ void saveState();
+ void restoreState();
+
template<typename Backend>
QVariantMap promptForSettings(const Backend *backend);
private:
template<typename Backend>
QVariantMap promptForSettings(const Backend *backend);
private:
+ static Core *_instance;
QSet<CoreAuthHandler *> _connectingClients;
QHash<UserId, SessionThread *> _sessions;
DeferredSharedPtr<Storage> _storage; ///< Active storage backend
QSet<CoreAuthHandler *> _connectingClients;
QHash<UserId, SessionThread *> _sessions;
DeferredSharedPtr<Storage> _storage; ///< Active storage backend
#include "core.h"
#include "coreapplication.h"
#include "core.h"
#include "coreapplication.h"
-CoreApplicationInternal::CoreApplicationInternal()
- : _coreCreated(false)
-{
-}
-
-
-CoreApplicationInternal::~CoreApplicationInternal()
-{
- if (_coreCreated) {
- Core::saveState();
- Core::destroy();
- }
-}
-
-
-bool CoreApplicationInternal::init()
-{
- Core::instance(); // create and init the core
- _coreCreated = true;
-
- Quassel::registerReloadHandler([]() {
- // Currently, only reloading SSL certificates and the sysident cache is supported
- Core::cacheSysIdent();
- return Core::reloadCerts();
- });
-
- if (!Quassel::isOptionSet("norestore"))
- Core::restoreState();
-
- return true;
-}
-
-
-/*****************************************************************************/
CoreApplication::CoreApplication(int &argc, char **argv)
: QCoreApplication(argc, argv)
CoreApplication::CoreApplication(int &argc, char **argv)
: QCoreApplication(argc, argv)
#endif /* Q_OS_MAC */
Quassel::setRunMode(Quassel::CoreOnly);
#endif /* Q_OS_MAC */
Quassel::setRunMode(Quassel::CoreOnly);
- _internal = new CoreApplicationInternal();
}
CoreApplication::~CoreApplication()
{
}
CoreApplication::~CoreApplication()
{
Quassel::destroy();
}
bool CoreApplication::init()
{
Quassel::destroy();
}
bool CoreApplication::init()
{
- return Quassel::init() && _internal->init();
+ if (Quassel::init()) {
+ _core.reset(new Core{}); // FIXME C++14: std::make_unique
+ return _core->init();
+ }
+ return false;
#include <QCoreApplication>
#include "quassel.h"
#include <QCoreApplication>
#include "quassel.h"
-/// Encapsulates CoreApplication's logic.
-/** This allows it to be reused within MonolithicApplication as well.
- */
-class CoreApplicationInternal
-{
- Q_DECLARE_TR_FUNCTIONS(CoreApplicationInternal)
-
-public:
- CoreApplicationInternal();
- ~CoreApplicationInternal();
-
- bool init();
-
-private:
- bool _coreCreated;
-};
-
class CoreApplication : public QCoreApplication
{
Q_OBJECT
public:
CoreApplication(int &argc, char **argv);
class CoreApplication : public QCoreApplication
{
Q_OBJECT
public:
CoreApplication(int &argc, char **argv);
+ ~CoreApplication() override;
- CoreApplicationInternal *_internal;
+ std::unique_ptr<Core> _core;
class InternalPeer;
MonolithicApplication::MonolithicApplication(int &argc, char **argv)
class InternalPeer;
MonolithicApplication::MonolithicApplication(int &argc, char **argv)
- : QtUiApplication(argc, argv),
- _internalInitDone(false)
+ : QtUiApplication(argc, argv)
- _internal = new CoreApplicationInternal(); // needed for parser options
#if defined(HAVE_KDE4) || defined(Q_OS_MAC)
Quassel::disableCrashHandler();
#endif /* HAVE_KDE4 || Q_OS_MAC */
#if defined(HAVE_KDE4) || defined(Q_OS_MAC)
Quassel::disableCrashHandler();
#endif /* HAVE_KDE4 || Q_OS_MAC */
connect(Client::coreConnection(), SIGNAL(startInternalCore()), SLOT(startInternalCore()));
connect(Client::coreConnection(), SIGNAL(startInternalCore()), SLOT(startInternalCore()));
- // If port is given, start core so it can listen to incoming connections
- if (Quassel::isOptionSet("port")) {
- startInternalCore();
- }
-
{
// Client needs to be destroyed first
Client::destroy();
{
// Client needs to be destroyed first
Client::destroy();
+ _core.reset();
+ Quassel::destroy();
}
void MonolithicApplication::startInternalCore()
{
}
void MonolithicApplication::startInternalCore()
{
- if (!_internalInitDone) {
- _internal->init();
- _internalInitDone = true;
+ if (!_core) {
+ _core.reset(new Core{}); // FIXME C++14: std::make_unique
+ Core::instance()->init();
- Core *core = Core::instance();
- CoreConnection *connection = Client::coreConnection();
- connect(connection, SIGNAL(connectToInternalCore(InternalPeer*)), core, SLOT(setupInternalClientSession(InternalPeer*)));
- connect(core, SIGNAL(sessionState(Protocol::SessionState)), connection, SLOT(internalSessionStateReceived(Protocol::SessionState)));
+ connect(Client::coreConnection(), SIGNAL(connectToInternalCore(InternalPeer*)), Core::instance(), SLOT(setupInternalClientSession(InternalPeer*)));
+ connect(Core::instance(), SIGNAL(sessionState(Protocol::SessionState)), Client::coreConnection(), SLOT(internalSessionStateReceived(Protocol::SessionState)));
#include "qtuiapplication.h"
#include "qtuiapplication.h"
-class CoreApplicationInternal;
class MonolithicApplication : public QtUiApplication
{
Q_OBJECT
public:
MonolithicApplication(int &, char **);
class MonolithicApplication : public QtUiApplication
{
Q_OBJECT
public:
MonolithicApplication(int &, char **);
- ~MonolithicApplication();
+ ~MonolithicApplication() override;
void startInternalCore();
private:
void startInternalCore();
private:
- CoreApplicationInternal *_internal;
- bool _internalInitDone;
+ std::unique_ptr<Core> _core;