// ==============================
// 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;
}
-Core::Core()
+Core::~Core()
+{
+ saveState();
+ qDeleteAll(_connectingClients);
+ qDeleteAll(_sessions);
+ syncStorage();
+ _instance = nullptr;
+}
+
+
+bool Core::init()
{
_startTime = QDateTime::currentDateTime().toUTC(); // for uptime :)
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");
qWarning() << "Cannot configure from environment";
exit(EXIT_FAILURE);
}
- } else {
+ }
+ else {
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)
}
- 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);
}
+
+ 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()));
- 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);
+ return true;
}
-
/*** 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()
{
- 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();
if (activeSessions.count() > 0) {
quInfo() << "Restoring previous core state...";
- foreach(QVariant v, activeSessions) {
+ for(auto &&v : activeSessions) {
UserId user = v.value<UserId>();
- instance()->sessionForUser(user, true);
+ sessionForUser(user, true);
}
}
}
bool Core::reloadCerts()
{
#ifdef HAVE_SSL
- SslServer *sslServerv4 = qobject_cast<SslServer *>(&instance()->_server);
+ SslServer *sslServerv4 = qobject_cast<SslServer *>(&_server);
bool retv4 = sslServerv4->reloadCerts();
- SslServer *sslServerv6 = qobject_cast<SslServer *>(&instance()->_v6server);
+ SslServer *sslServerv6 = qobject_cast<SslServer *>(&_v6server);
bool retv6 = sslServerv6->reloadCerts();
return retv4 && retv6;
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!
- cacheSysIdent();
+ instance()->cacheSysIdent();
if (_authUserNames.contains(user)) {
return _authUserNames[user];
public:
static Core *instance();
- static void destroy();
- static void saveState();
- static void restoreState();
+ Core();
+ ~Core() override;
/*** Storage access ***/
// These methods are threadsafe.
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 const int AddClientEventId;
public slots:
- //! Make storage data persistent
- /** \note This method is threadsafe.
+ bool init();
+
+ /** Persist storage.
+ *
+ * @note This method is threadsafe.
*/
void syncStorage();
+
+ /**
+ * 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 sessionState(const Protocol::SessionState &sessionState);
protected:
- virtual void customEvent(QEvent *event);
+ void customEvent(QEvent *event) override;
private slots:
bool startListening();
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);
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:
+ static Core *_instance;
QSet<CoreAuthHandler *> _connectingClients;
QHash<UserId, SessionThread *> _sessions;
DeferredSharedPtr<Storage> _storage; ///< Active storage backend
#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)
#endif /* Q_OS_MAC */
Quassel::setRunMode(Quassel::CoreOnly);
- _internal = new CoreApplicationInternal();
}
CoreApplication::~CoreApplication()
{
- delete _internal;
+ _core.reset();
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;
}
#pragma once
+#include <memory>
+
#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 Core;
class CoreApplication : public QCoreApplication
{
Q_OBJECT
public:
CoreApplication(int &argc, char **argv);
- ~CoreApplication();
+ ~CoreApplication() override;
bool init();
private:
- CoreApplicationInternal *_internal;
+ std::unique_ptr<Core> _core;
};
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 */
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();
- }
-
return true;
}
{
// Client needs to be destroyed first
Client::destroy();
- delete _internal;
+ _core.reset();
+ Quassel::destroy();
}
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)));
}
#pragma once
+#include <memory>
+
#include "qtuiapplication.h"
-class CoreApplicationInternal;
+class Core;
class MonolithicApplication : public QtUiApplication
{
Q_OBJECT
public:
MonolithicApplication(int &, char **);
- ~MonolithicApplication();
+ ~MonolithicApplication() override;
bool init() override;
void startInternalCore();
private:
- CoreApplicationInternal *_internal;
- bool _internalInitDone;
+ std::unique_ptr<Core> _core;
};