-CoreSession::CoreSession(UserId uid, bool restoreState, QObject *parent)
- : QObject(parent),
- _user(uid),
- _signalProxy(new SignalProxy(SignalProxy::Server, 0, this)),
- _aliasManager(this),
- _bufferSyncer(new CoreBufferSyncer(this)),
- _backlogManager(new CoreBacklogManager(this)),
- _bufferViewManager(new CoreBufferViewManager(_signalProxy, this)),
- _ircListHelper(new CoreIrcListHelper(this)),
- _networkConfig(new CoreNetworkConfig("GlobalNetworkConfig", this)),
- _coreInfo(this),
- _eventManager(new CoreEventManager(this)),
- _eventStringifier(new EventStringifier(this)),
- _sessionEventProcessor(new CoreSessionEventProcessor(this)),
- _ctcpParser(new CtcpParser(this)),
- _ircParser(new IrcParser(this)),
- scriptEngine(new QScriptEngine(this)),
- _processMessages(false),
- _ignoreListManager(this)
-{
- SignalProxy *p = signalProxy();
- p->setHeartBeatInterval(30);
- p->setMaxHeartBeatCount(60); // 30 mins until we throw a dead socket out
-
- connect(p, SIGNAL(peerRemoved(QIODevice *)), this, SLOT(removeClient(QIODevice *)));
-
- connect(p, SIGNAL(connected()), this, SLOT(clientsConnected()));
- connect(p, SIGNAL(disconnected()), this, SLOT(clientsDisconnected()));
-
- p->attachSlot(SIGNAL(sendInput(BufferInfo, QString)), this, SLOT(msgFromClient(BufferInfo, QString)));
- p->attachSignal(this, SIGNAL(displayMsg(Message)));
- p->attachSignal(this, SIGNAL(displayStatusMsg(QString, QString)));
-
- p->attachSignal(this, SIGNAL(identityCreated(const Identity &)));
- p->attachSignal(this, SIGNAL(identityRemoved(IdentityId)));
- p->attachSlot(SIGNAL(createIdentity(const Identity &, const QVariantMap &)), this, SLOT(createIdentity(const Identity &, const QVariantMap &)));
- p->attachSlot(SIGNAL(removeIdentity(IdentityId)), this, SLOT(removeIdentity(IdentityId)));
-
- p->attachSignal(this, SIGNAL(networkCreated(NetworkId)));
- p->attachSignal(this, SIGNAL(networkRemoved(NetworkId)));
- p->attachSlot(SIGNAL(createNetwork(const NetworkInfo &, const QStringList &)), this, SLOT(createNetwork(const NetworkInfo &, const QStringList &)));
- p->attachSlot(SIGNAL(removeNetwork(NetworkId)), this, SLOT(removeNetwork(NetworkId)));
-
- loadSettings();
- initScriptEngine();
-
- eventManager()->registerObject(ircParser(), EventManager::NormalPriority);
- eventManager()->registerObject(sessionEventProcessor(), EventManager::HighPriority); // needs to process events *before* the stringifier!
- eventManager()->registerObject(ctcpParser(), EventManager::NormalPriority);
- eventManager()->registerObject(eventStringifier(), EventManager::NormalPriority);
- eventManager()->registerObject(this, EventManager::LowPriority); // for sending MessageEvents to the client
- // some events need to be handled after msg generation
- eventManager()->registerObject(sessionEventProcessor(), EventManager::LowPriority, "lateProcess");
- eventManager()->registerObject(ctcpParser(), EventManager::LowPriority, "send");
-
- // periodically save our session state
- connect(&(Core::instance()->syncTimer()), SIGNAL(timeout()), this, SLOT(saveSessionState()));
-
- p->synchronize(_bufferSyncer);
- p->synchronize(&aliasManager());
- p->synchronize(_backlogManager);
- p->synchronize(ircListHelper());
- p->synchronize(networkConfig());
- p->synchronize(&_coreInfo);
- p->synchronize(&_ignoreListManager);
- // Restore session state
- if(restoreState)
- restoreSessionState();
-
- emit initialized();
-}
-
-CoreSession::~CoreSession() {
- saveSessionState();
- foreach(CoreNetwork *net, _networks.values()) {
- delete net;
- }
-}
-
-CoreNetwork *CoreSession::network(NetworkId id) const {
- if(_networks.contains(id)) return _networks[id];
- return 0;
-}
-
-CoreIdentity *CoreSession::identity(IdentityId id) const {
- if(_identities.contains(id)) return _identities[id];
- return 0;
-}
-
-void CoreSession::loadSettings() {
- CoreUserSettings s(user());
-
- // migrate to db
- QList<IdentityId> ids = s.identityIds();
- QList<NetworkInfo> networkInfos = Core::networks(user());
- foreach(IdentityId id, ids) {
- CoreIdentity identity(s.identity(id));
- IdentityId newId = Core::createIdentity(user(), identity);
- QList<NetworkInfo>::iterator networkIter = networkInfos.begin();
- while(networkIter != networkInfos.end()) {
- if(networkIter->identity == id) {
- networkIter->identity = newId;
- Core::updateNetwork(user(), *networkIter);
- networkIter = networkInfos.erase(networkIter);
- } else {
- networkIter++;
- }
- }
- s.removeIdentity(id);
- }
- // end of migration
-
- foreach(CoreIdentity identity, Core::identities(user())) {
- createIdentity(identity);
- }
-
- foreach(NetworkInfo info, Core::networks(user())) {
- createNetwork(info);
- }
-}
-
-void CoreSession::saveSessionState() const {
- _bufferSyncer->storeDirtyIds();
- _bufferViewManager->saveBufferViews();
- _networkConfig->save();
-}
-
-void CoreSession::restoreSessionState() {
- QList<NetworkId> nets = Core::connectedNetworks(user());
- CoreNetwork *net = 0;
- foreach(NetworkId id, nets) {
- net = network(id);
- Q_ASSERT(net);
- net->connectToIrc();
- }
+CoreSession::CoreSession(UserId uid, bool restoreState, bool strictIdentEnabled, QObject* parent)
+ : QObject(parent)
+ , _user(uid)
+ , _strictIdentEnabled(strictIdentEnabled)
+ , _signalProxy(new SignalProxy(SignalProxy::Server, this))
+ , _aliasManager(this)
+ , _bufferSyncer(new CoreBufferSyncer(this))
+ , _backlogManager(new CoreBacklogManager(this))
+ , _bufferViewManager(new CoreBufferViewManager(_signalProxy, this))
+ , _dccConfig(new CoreDccConfig(this))
+ , _ircListHelper(new CoreIrcListHelper(this))
+ , _networkConfig(new CoreNetworkConfig("GlobalNetworkConfig", this))
+ , _coreInfo(new CoreInfo(this))
+ , _transferManager(new CoreTransferManager(this))
+ , _eventManager(new CoreEventManager(this))
+ , _eventStringifier(new EventStringifier(this))
+ , _sessionEventProcessor(new CoreSessionEventProcessor(this))
+ , _ctcpParser(new CtcpParser(this))
+ , _ircParser(new IrcParser(this))
+ , _processMessages(false)
+ , _ignoreListManager(this)
+ , _highlightRuleManager(this)
+ , _metricsServer(Core::instance()->metricsServer())
+{
+ SignalProxy* p = signalProxy();
+ p->setHeartBeatInterval(30);
+ p->setMaxHeartBeatCount(60); // 30 mins until we throw a dead socket out
+
+ connect(p, &SignalProxy::peerRemoved, this, &CoreSession::removeClient);
+
+ connect(p, &SignalProxy::connected, this, &CoreSession::clientsConnected);
+ connect(p, &SignalProxy::disconnected, this, &CoreSession::clientsDisconnected);
+
+ p->attachSlot(SIGNAL(sendInput(BufferInfo,QString)), this, &CoreSession::msgFromClient);
+ p->attachSignal(this, &CoreSession::displayMsg);
+ p->attachSignal(this, &CoreSession::displayStatusMsg);
+
+ p->attachSignal(this, &CoreSession::identityCreated);
+ p->attachSignal(this, &CoreSession::identityRemoved);
+ p->attachSlot(SIGNAL(createIdentity(Identity,QVariantMap)), this, selectOverload<const Identity&, const QVariantMap&>(&CoreSession::createIdentity));
+ p->attachSlot(SIGNAL(removeIdentity(IdentityId)), this, &CoreSession::removeIdentity);
+
+ p->attachSignal(this, &CoreSession::networkCreated);
+ p->attachSignal(this, &CoreSession::networkRemoved);
+ p->attachSlot(SIGNAL(createNetwork(NetworkInfo,QStringList)), this,&CoreSession::createNetwork);
+ p->attachSlot(SIGNAL(removeNetwork(NetworkId)), this, &CoreSession::removeNetwork);
+
+ p->attachSlot(SIGNAL(changePassword(PeerPtr,QString,QString,QString)), this, &CoreSession::changePassword);
+ p->attachSignal(this, &CoreSession::passwordChanged);
+
+ p->attachSlot(SIGNAL(kickClient(int)), this, &CoreSession::kickClient);
+ p->attachSignal(this, &CoreSession::disconnectFromCore);
+
+ QVariantMap data;
+ data["quasselVersion"] = Quassel::buildInfo().fancyVersionString;
+ data["quasselBuildDate"] = Quassel::buildInfo().commitDate; // "BuildDate" for compatibility
+ data["startTime"] = Core::startTime();
+ data["sessionConnectedClients"] = 0;
+ _coreInfo->setCoreData(data);
+
+ loadSettings();
+
+ eventManager()->registerObject(ircParser(), EventManager::NormalPriority);
+ eventManager()->registerObject(sessionEventProcessor(), EventManager::HighPriority); // needs to process events *before* the stringifier!
+ eventManager()->registerObject(ctcpParser(), EventManager::NormalPriority);
+ eventManager()->registerObject(eventStringifier(), EventManager::NormalPriority);
+ eventManager()->registerObject(this, EventManager::LowPriority); // for sending MessageEvents to the client
+ // some events need to be handled after msg generation
+ eventManager()->registerObject(sessionEventProcessor(), EventManager::LowPriority, "lateProcess");
+ eventManager()->registerObject(ctcpParser(), EventManager::LowPriority, "send");
+
+ // periodically save our session state
+ connect(Core::syncTimer(), &QTimer::timeout, this, &CoreSession::saveSessionState);
+
+ p->synchronize(_bufferSyncer);
+ p->synchronize(&aliasManager());
+ p->synchronize(_backlogManager);
+ p->synchronize(dccConfig());
+ p->synchronize(ircListHelper());
+ p->synchronize(networkConfig());
+ p->synchronize(_coreInfo);
+ p->synchronize(&_ignoreListManager);
+ p->synchronize(&_highlightRuleManager);
+ // Listen to network removed events
+ connect(this, &CoreSession::networkRemoved, &_highlightRuleManager, &HighlightRuleManager::networkRemoved);
+ p->synchronize(transferManager());
+ // Restore session state
+ if (restoreState)
+ restoreSessionState();
+
+ emit initialized();
+
+ if (_metricsServer) {
+ _metricsServer->addSession(user(), Core::instance()->strictSysIdent(_user));
+ }
+}
+
+void CoreSession::shutdown()
+{
+ saveSessionState();
+
+ // Request disconnect from all connected networks in parallel, and wait until every network
+ // has emitted the disconnected() signal before deleting the session itself
+ for (CoreNetwork* net : _networks.values()) {
+ if (net->socketState() != QAbstractSocket::UnconnectedState) {
+ _networksPendingDisconnect.insert(net->networkId());
+ connect(net, &CoreNetwork::disconnected, this, &CoreSession::onNetworkDisconnected);
+ net->shutdown();
+ }
+ }
+
+ if (_networksPendingDisconnect.isEmpty()) {
+ // Nothing to do, suicide so the core can shut down
+ deleteLater();
+ }
+
+ if (_metricsServer) {
+ _metricsServer->removeSession(user());
+ }
+}
+
+void CoreSession::onNetworkDisconnected(NetworkId networkId)
+{
+ _networksPendingDisconnect.remove(networkId);
+ if (_networksPendingDisconnect.isEmpty()) {
+ // We're done, suicide so the core can shut down
+ deleteLater();
+ }
+}
+
+CoreNetwork* CoreSession::network(NetworkId id) const
+{
+ if (_networks.contains(id))
+ return _networks[id];
+ return nullptr;
+}
+
+CoreIdentity* CoreSession::identity(IdentityId id) const
+{
+ if (_identities.contains(id))
+ return _identities[id];
+ return nullptr;
+}
+
+void CoreSession::loadSettings()
+{
+ CoreUserSettings s(user());
+
+ // migrate to db
+ QList<IdentityId> ids = s.identityIds();
+ QList<NetworkInfo> networkInfos = Core::networks(user());
+ for (IdentityId id : ids) {
+ CoreIdentity identity(s.identity(id));
+ IdentityId newId = Core::createIdentity(user(), identity);
+ QList<NetworkInfo>::iterator networkIter = networkInfos.begin();
+ while (networkIter != networkInfos.end()) {
+ if (networkIter->identity == id) {
+ networkIter->identity = newId;
+ Core::updateNetwork(user(), *networkIter);
+ networkIter = networkInfos.erase(networkIter);
+ }
+ else {
+ ++networkIter;
+ }
+ }
+ s.removeIdentity(id);
+ }
+ // end of migration
+
+ for (const CoreIdentity& identity : Core::identities(user())) {
+ createIdentity(identity);
+ }
+
+ for (const NetworkInfo& info : Core::networks(user())) {
+ createNetwork(info);
+ }
+}
+
+void CoreSession::saveSessionState() const
+{
+ _bufferSyncer->storeDirtyIds();
+ _bufferViewManager->saveBufferViews();
+ _networkConfig->save();
+}
+
+void CoreSession::restoreSessionState()
+{
+ QList<NetworkId> nets = Core::connectedNetworks(user());
+ CoreNetwork* net = nullptr;
+ for (NetworkId id : nets) {
+ net = network(id);
+ Q_ASSERT(net);
+ net->connectToIrc();
+ }
+}
+
+void CoreSession::addClient(RemotePeer* peer)
+{
+ signalProxy()->setTargetPeer(peer);
+
+ peer->dispatch(sessionState());
+ signalProxy()->addPeer(peer);
+ _coreInfo->setConnectedClientData(signalProxy()->peerCount(), signalProxy()->peerData());
+
+ signalProxy()->setTargetPeer(nullptr);
+
+ if (_metricsServer) {
+ _metricsServer->addClient(user());
+ }